diff options
| author | Roy <Roy.mail.net@gmail.com> | 2022-11-13 03:46:12 +0200 |
|---|---|---|
| committer | Roy <Roy.mail.net@gmail.com> | 2022-11-13 03:46:12 +0200 |
| commit | d38bf750367c6d6cdda3a6a3efbdf3552aa85358 (patch) | |
| tree | 000818a2a1e49d1e3decc630a94cf183bbaf2128 /Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs | |
| parent | 8431040bf909ba65d5ce242b5fd2cc91005ba679 (diff) | |
| download | Tango-d38bf750367c6d6cdda3a6a3efbdf3552aa85358.tar.gz Tango-d38bf750367c6d6cdda3a6a3efbdf3552aa85358.zip | |
FSE Stats Module.
Extended job run structure.
CSV export.
Diffstat (limited to 'Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs')
| -rw-r--r-- | Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs | 486 |
1 files changed, 466 insertions, 20 deletions
diff --git a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs index 2a14b7de1..c85a411e3 100644 --- a/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/FSE/Modules/Tango.FSE.Statistics/ViewModels/MainViewVM.cs @@ -1,14 +1,24 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Data.Entity; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Windows.Data; +using Tango.BL; +using Tango.BL.DTO; +using Tango.BL.Entities; using Tango.BL.Enumerations; +using Tango.Core.Commands; +using Tango.CSV; using Tango.FSE.Common; using Tango.FSE.Common.AutoComplete; using Tango.FSE.Common.Navigation; +using Tango.FSE.Common.Notifications; +using Tango.FSE.Common.Statistics; +using Tango.FSE.Statistics.Models; using Tango.PPC.Shared.Statistics; using Tango.SharedUI.Components; using Tango.SharedUI.Helpers; @@ -17,6 +27,48 @@ namespace Tango.FSE.Statistics.ViewModels { public class MainViewVM : FSEViewModel { + private List<ProcessParametersTable> _processTables; + + private DateTime _startSelectedDate; + public DateTime StartSelectedDate + { + get { return _startSelectedDate; } + set + { + _startSelectedDate = value; + RaisePropertyChangedAuto(); + } + } + + private DateTime _endSelectedDate; + public DateTime EndSelectedDate + { + get { return _endSelectedDate; } + set { _endSelectedDate = value; RaisePropertyChangedAuto(); } + } + + protected Double _lengthLowerValue; + public Double LengthLowerValue + { + get { return _lengthLowerValue; } + set + { + _lengthLowerValue = value; + RaisePropertyChangedAuto(); + } + } + + protected Double _lengthUpperValue; + public Double LengthUpperValue + { + get { return _lengthUpperValue; } + set + { + _lengthUpperValue = value; + RaisePropertyChangedAuto(); + } + } + private RequiredFiltersData _filtersData; public RequiredFiltersData FiltersData { @@ -38,10 +90,82 @@ namespace Tango.FSE.Statistics.ViewModels set { _selectedThreads = value; RaisePropertyChangedAuto(); } } + private String _jobName; + public String JobName + { + get { return _jobName; } + set { _jobName = value; RaisePropertyChangedAuto(); } + } + + private bool _includeHeadCleaning; + public bool IncludeHeadCleaning + { + get { return _includeHeadCleaning; } + set { _includeHeadCleaning = value; RaisePropertyChangedAuto(); } + } + + private bool _isSettingsBarOpened; + public bool IsSettingsBarOpened + { + get { return _isSettingsBarOpened; } + set { _isSettingsBarOpened = value; RaisePropertyChangedAuto(); } + } + + private bool _isFiltersAvailable; + public bool IsFiltersAvailable + { + get { return _isFiltersAvailable; } + set { _isFiltersAvailable = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } + } + + private List<StopModel> _stops; + public List<StopModel> Stops + { + get { return _stops; } + set { _stops = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(IsResultsAvailable)); InvalidateRelayCommands(); } + } + + private ListCollectionView _stopView; + public ListCollectionView StopsView + { + get { return _stopView; } + set { _stopView = value; RaisePropertyChangedAuto(); } + } + + private bool _jobNameExact; + public bool JobNameExact + { + get { return _jobNameExact; } + set { _jobNameExact = value; RaisePropertyChangedAuto(); } + } + + public RelayCommand GetStatisticsCommand { get; set; } + public AutoCompleteSource<String> JobsAutoCompleteProvider { get; set; } + private StatsModel _stats; + public StatsModel Stats + { + get { return _stats; } + set { _stats = value; RaisePropertyChangedAuto(); } + } + + public bool IsResultsAvailable + { + get { return Stops != null && Stops.Count > 0 && Stops[0].JobIndex != -1000; } + } + + public RelayCommand<StopModel> ShowFailedMessageCommand { get; set; } + + public RelayCommand ExportToCsvCommand { get; set; } + + public MainViewVM() { + IsSettingsBarOpened = true; + + _processTables = new List<ProcessParametersTable>(); + JobRunSelectedStatuses = new SelectedObjectCollection<JobRunStatus>(new ObservableCollection<JobRunStatus>() { JobRunStatus.Aborted, @@ -58,15 +182,31 @@ namespace Tango.FSE.Statistics.ViewModels JobRunSelectedStatuses.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(JobRunSelectedStatuses)); JobRunSelectedStatuses.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(JobRunSelectedStatuses)); - FiltersData = new RequiredFiltersData(); - JobsAutoCompleteProvider = new AutoCompleteSource<string>(AutoCompleteJobs); + + StartSelectedDate = DateTime.Now.AddYears(-7); + EndSelectedDate = DateTime.Now; + LengthUpperValue = 10000; + + GetStatisticsCommand = new RelayCommand(GetStatistics, () => IsFiltersAvailable); + + //Just for showing the columns :/ + Stops = new List<StopModel>() { new StopModel() { JobRun = new JobRunDTO(), Job = new PresentationJob(), JobIndex = -1000 } }; + var view = new ListCollectionView(Stops); + view.GroupDescriptions.Add(new PropertyGroupDescription("JobIndex")); + view.GroupDescriptions.Add(new PropertyGroupDescription("SegmentIndex")); + StopsView = view; + + Stats = new StatsModel(); + + ShowFailedMessageCommand = new RelayCommand<StopModel>(ShowJobRunFailedMessage); + ExportToCsvCommand = new RelayCommand(ExportToCSV, () => IsResultsAvailable); } private List<String> AutoCompleteJobs(string key) { key = key ?? String.Empty; - return FiltersData.Jobs.Where(x => x.ToLower().Contains(key.ToLower())).ToList(); + return FiltersData.Jobs.Where(x => x != null).Where(x => x.ToLower().Contains(key.ToLower())).ToList(); } public override void OnApplicationStarted() @@ -86,32 +226,338 @@ namespace Tango.FSE.Statistics.ViewModels }); } - public async override void OnNavigatedTo() + public async override void OnApplicationReady() { - base.OnNavigatedTo(); - await LoadFiltersData(); - await LoadStatistics(); + base.OnApplicationReady(); + + MachineProvider.MachineConnected += MachineProvider_MachineConnected; + MachineProvider.MachineDisconnected += MachineProvider_MachineDisconnected; + + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + _processTables = await db.ProcessParametersTables.ToListAsync(); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error loading process parameters tables for statistics."); + } + } + + private void MachineProvider_MachineDisconnected(object sender, Common.Connection.MachineDisconnectedEventArgs e) + { + + } + + private async void MachineProvider_MachineConnected(object sender, Common.Connection.MachineConnectedEventArgs e) + { + if (MachineProvider.IsPPCAvailable && (e.DifferentFromPrevious || !IsFiltersAvailable)) + { + await LoadFiltersData(); + } } private async Task LoadFiltersData() { - FiltersData = await StatisticsProvider.GetRequiredFiltersData(); - SelectedThreads = new SelectedObjectCollection<ThreadFilterData>(FiltersData.Rmls.ToObservableCollection(), new ObservableCollection<ThreadFilterData>()); + try + { + FiltersData = await StatisticsProvider.GetRequiredFiltersData(); + SelectedThreads = new SelectedObjectCollection<ThreadFilterData>(FiltersData.Rmls.ToObservableCollection(), new ObservableCollection<ThreadFilterData>()); + IsFiltersAvailable = true; + } + catch (Exception ex) + { + IsFiltersAvailable = false; + NotificationProvider.PushErrorReportingSnackbar(ex, "Statistics Module Error", "Error loading required statistics filter data."); + } + } + + private async void GetStatistics() + { + StatisticsModel model = null; + try + { + using (var task = NotificationProvider.PushTaskItem("Getting statistics from the remote machine...", false)) + { + await Task.Delay(3000); + + Filters filters = new Filters(); + filters.StartDateUTC = StartSelectedDate; + filters.EndDateUTC = EndSelectedDate; + filters.EndStatuses = JobRunSelectedStatuses.SynchedSource.Cast<int>().ToList(); + filters.IncludeHeadCleaning = IncludeHeadCleaning; + filters.JobName = JobName; + filters.ExactJobName = JobNameExact; + filters.MinLength = (int)LengthLowerValue; + filters.MaxLength = (int)LengthUpperValue; + filters.RmlGuids = SelectedThreads.SynchedSource.Select(x => x.Guid).ToList(); + + model = await StatisticsProvider.GetStatistics(filters); + + List<StopModel> stops = new List<StopModel>(); + + int jobIndex = 0; + + foreach (var job in model.StatisticsResult.JobRuns.OrderByDescending(x => x.JobRun.StartDate)) + { + var rmlName = FiltersData.Rmls.FirstOrDefault(x => x.Guid == job.JobRun.RmlGuid)?.Name; + var processTable = _processTables.FirstOrDefault(x => x.Guid == job.JobRun.ProcessParametersTableGuid); + + jobIndex++; + + foreach (var jobSegment in job.Job.Segments) + { + foreach (var jobStop in jobSegment.Stops) + { + StopModel stop = new StopModel(); + stop.JobIndex = jobIndex; + stop.SegmentIndex = job.Job.Segments.IndexOf(jobSegment) + 1; + stop.ThreadName = rmlName; + stop.ProcessParameters = processTable; + stop.IsAdvancedMode = !BuildProvider.IsTwineStudio && CurrentUser.HasRole(Roles.FSETwineTechnician); + + stop.ColorSpace = jobStop.ColorSpace; + + stop.L = jobStop.L; + stop.A = jobStop.A; + stop.B = jobStop.B; + + stop.Red = jobStop.Red; + stop.Green = jobStop.Green; + stop.Blue = jobStop.Blue; + + stop.Cyan = jobStop.Cyan; + stop.Magenta = jobStop.Magenta; + stop.Yellow = jobStop.Yellow; + stop.Black = jobStop.Black; + + stop.Catalog = jobStop.Catalog; + stop.CatalogItem = jobStop.CatalogItem; + + stop.StartMeters = jobStop.StartMeters; + + stop.Job = job.Job; + stop.JobRun = job.JobRun; + stop.Segment = jobSegment; + + stop.LiquidVolumes = jobStop.LiquidVolumes; + stop.BestMatchR = jobStop.BestMatchR; + stop.BestMatchG = jobStop.BestMatchG; + stop.BestMatchB = jobStop.BestMatchB; + + stop.ShowFailedMessageCommand = ShowFailedMessageCommand; + + stops.Add(stop); + } + } + } + + Stops = stops; + + var view = new ListCollectionView(Stops); + view.GroupDescriptions.Add(new PropertyGroupDescription("JobIndex")); + view.GroupDescriptions.Add(new PropertyGroupDescription("SegmentIndex")); + + StopsView = view; + + var stats = new StatsModel(); + + try + { + stats.TotalRuns = model.StatisticsResult.JobRuns.Count; + stats.CompletedRuns = model.StatisticsResult.JobRuns.Count(x => x.JobRun.Status == (int)JobRunStatus.Completed); + stats.FailedRuns = model.StatisticsResult.JobRuns.Count(x => x.JobRun.Status == (int)JobRunStatus.Failed); + stats.AbortedRuns = model.StatisticsResult.JobRuns.Count(x => x.JobRun.Status == (int)JobRunStatus.Aborted); + stats.TotalDyeingLength = (int)model.StatisticsResult.JobRuns.Where(x => x.JobRun.EndPosition > 0).Select(x => x.JobRun.EndPosition).Sum(); + stats.AverageDyeingLength = (int)model.StatisticsResult.JobRuns.Where(x => x.JobRun.EndPosition > 0).Select(x => x.JobRun.EndPosition).Average(); + + var timeRuns = model.StatisticsResult.JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.EndDate != null && z.JobRun.ActualStartDate != null).ToList(); + + stats.TotalDyeingTime = TimeSpan.FromHours(timeRuns.Sum(x => (x.JobRun.EndDate - x.JobRun.ActualStartDate.Value).TotalHours)); + stats.AverageDyeingTime = TimeSpan.FromHours(timeRuns.Average(x => (x.JobRun.EndDate - x.JobRun.ActualStartDate.Value).TotalHours)); + + List<LiquidQuantityModel> liquidQuantities = new List<LiquidQuantityModel>(); + + Dictionary<LiquidTypes, double> quantities = new Dictionary<LiquidTypes, double>(); + quantities.Add(LiquidTypes.Cyan, 0); + quantities.Add(LiquidTypes.Magenta, 0); + quantities.Add(LiquidTypes.Yellow, 0); + quantities.Add(LiquidTypes.Black, 0); + quantities.Add(LiquidTypes.LightCyan, 0); + quantities.Add(LiquidTypes.LightMagenta, 0); + quantities.Add(LiquidTypes.LightYellow, 0); + quantities.Add(LiquidTypes.TransparentInk, 0); + quantities.Add(LiquidTypes.Lubricant, 0); + + foreach (var stop in stops) + { + quantities[LiquidTypes.Cyan] += stop.JobRun.CyanQuantity; + quantities[LiquidTypes.Magenta] += stop.JobRun.MagentaQuantity; + quantities[LiquidTypes.Yellow] += stop.JobRun.YellowQuantity; + quantities[LiquidTypes.Black] += stop.JobRun.BlackQuantity; + quantities[LiquidTypes.LightCyan] += stop.JobRun.LightCyanQuantity; + quantities[LiquidTypes.LightMagenta] += stop.JobRun.LightMagentaQuantity; + quantities[LiquidTypes.LightYellow] += stop.JobRun.LightYellowQuantity; + quantities[LiquidTypes.TransparentInk] += stop.JobRun.TransparentQuantity; + quantities[LiquidTypes.Lubricant] += stop.JobRun.LubricantQuantity; + } + + foreach (var item in quantities) + { + liquidQuantities.Add(new LiquidQuantityModel() { LiquidType = item.Key, Quantity = item.Value }); + } + + stats.LiquidQuantities = liquidQuantities; + } + catch (Exception ex) + { + LogManager.Log(ex, "Error generating statistics summaries."); + } + + Stats = stats; + + if (Stops.Count > 0) + { + await Task.Delay(1000); + + IsSettingsBarOpened = false; + + await Task.Delay(1000); + } + } + } + catch (Exception ex) + { + NotificationProvider.PushErrorReportingSnackbar(ex, "Statistics Module Error", "Error statistics from the remote machine."); + } + } + + private async void ShowJobRunFailedMessage(StopModel stop) + { + await NotificationProvider.ShowError($"Job Failure Message:\n{stop.JobRun.FailedMessage}"); } - private async Task LoadStatistics() + private async void ExportToCSV() { - Filters filters = new Filters(); - filters.StartDateUTC = DateTime.Now.AddYears(-1).ToUniversalTime(); - filters.EndDateUTC = DateTime.Now.ToUniversalTime(); - filters.EndStatuses = JobRunSelectedStatuses.SynchedSource.Cast<int>().ToList(); - filters.IncludeHeadCleaning = false; - filters.JobName = null; - filters.MinLength = 0; - filters.MaxLength = 10000; - filters.RmlGuids = SelectedThreads.SynchedSource.Select(x => x.Guid).ToList(); + var result = await StorageProvider.SaveFile("Export To CSV File", "CSV Files|*.csv", $"{MachineProvider.Machine.SerialNumber}_JobRuns_{DateTime.Now.ToFileName()}.csv", ".csv"); + if (result.Confirmed) + { + using (NotificationProvider.PushTaskItem("Exporting job runs to file...")) + { + await Task.Delay(1000); + + try + { + CsvFile<CsvModel> csvFile = new CsvFile<CsvModel>(new CsvDestination(result.SelectedItem), new CsvDefinition() + { + Columns = new List<String>() + { + "Job Index", + "Job Name", + "Thread", + "Length", + "Start Time", + "Duration", + "End Position", + "Status", + "Segment Index", + "Offset", + "Color Space", + "Input Red", + "Input Green", + "Input Blue", + "Input L", + "Input A", + "Input B", + "Input Catalog", + "Input Catalog Item", + "Input Cyan", + "Input Magenta", + "Input Yellow", + "Input Black", + "Output Cyan", + "Output Magenta", + "Output Yellow", + "Output Black", + "Output Light Cyan", + "Output Light Magenta", + "Output Light Yellow", + "Output Transparent Ink", + "Output Lubricant", + "Failure Reason", + }, + }); + + foreach (var stop in Stops.OrderBy(x => x.JobIndex).ToList()) + { + CsvModel model = new CsvModel(); + model.JobIndex = stop.JobIndex.ToString(); + model.JobName = stop.JobRun.JobName; + model.Thread = stop.ThreadName; + model.Length = ((int)stop.JobRun.JobLength).ToString(); + model.StartTime = stop.JobRun.StartDate.ToLocalTime().ToString(); + model.Duration = stop.Duration.ToStringUnlimitedHours(); + model.EndPosition = stop.JobRun.EndPosition.ToString(); + model.Status = ((JobRunStatus)stop.JobRun.Status).ToString(); + model.SegmentIndex = stop.SegmentIndex.ToString(); + model.Offset = stop.StartMeters.ToString(); + model.ColorSpace = stop.ColorSpace.ToString(); + + switch (stop.ColorSpace) + { + case ColorSpaces.RGB: + model.InputRed = stop.Red.ToString(); + model.InputGreen = stop.Green.ToString(); + model.InputBlue = stop.Blue.ToString(); + break; + case ColorSpaces.LAB: + model.InputL = stop.L.ToString(); + model.InputA = stop.A.ToString(); + model.InputB = stop.B.ToString(); + break; + case ColorSpaces.Catalog: + model.InputCatalog = stop.Catalog; + model.InputCatalogItem = stop.CatalogItem; + break; + case ColorSpaces.Volume: + model.InputCyan = stop.Cyan.ToString(); + model.InputMagenta = stop.Magenta.ToString(); + model.InputYellow = stop.Yellow.ToString(); + model.InputBlack = stop.Black.ToString(); + break; + } + + + model.OutputCyan = stop.CyanOutput.ToString(); + model.OutputMagenta = stop.MagentaOutput.ToString(); + model.OutputYellow = stop.YellowOutput.ToString(); + model.OutputBlack = stop.BlackOutput.ToString(); + model.OutputLightCyan = stop.LightCyanOutput.ToString(); + model.OutputLightMagenta = stop.LightMagentaOutput.ToString(); + model.OutputLightYellow = stop.LightYellowOutput.ToString(); + model.OutputTransparentInk = stop.TransparentInkOutput.ToString(); + model.OutputLubricant = stop.LubricantOutput.ToString(); + model.FailureReason = stop.JobRun.FailedMessage; + + csvFile.Append(model); + } + + csvFile.Dispose(); - var model = await StatisticsProvider.GetStatistics(filters); + NotificationProvider.PushSnackbarItem(MessageType.Success, "Statistics File Export", true, "Export completed successfully.\nTap to open the file.", null, null, async () => + { + await StorageProvider.ShowInExplorer(result.SelectedItem); + }); + } + catch (Exception ex) + { + LogManager.Log(ex, "Error exporting csv file."); + await NotificationProvider.ShowError($"Error exporting the csv file.\n{ex.FlattenMessage()}"); + } + } + } } } } |
