aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2020-02-26 18:43:43 +0200
committerRoy Ben-Shabat <Roy@Twine-s.com>2020-02-26 18:43:43 +0200
commit8e5ab17ced647a8c9fbba764c6fa0c06d56269c9 (patch)
tree4d958c4775ac237f5d67803192aa530a80d978b7 /Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels
parentafb6bbb2123932b3562e1af993eb847d8147bf58 (diff)
parent228dca3384369f23d6dcad6a696cf491ab9d8840 (diff)
downloadTango-8e5ab17ced647a8c9fbba764c6fa0c06d56269c9.tar.gz
Tango-8e5ab17ced647a8c9fbba764c6fa0c06d56269c9.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels')
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs362
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs304
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs339
3 files changed, 680 insertions, 325 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs
new file mode 100644
index 000000000..b06261306
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs
@@ -0,0 +1,362 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Media;
+using Tango.BL.Enumerations;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Statistics.Models;
+using Tango.BL.Entities;
+using Tango.SharedUI;
+using Tango.BL;
+using Tango.MachineStudio.Common.Notifications;
+using System.Threading.Tasks;
+
+namespace Tango.MachineStudio.Statistics.ViewModels
+{
+ public class ChartsViewVM : ViewModel
+ {
+ private INotificationProvider _notification;
+ private ObservablesContext _context;
+ private List<JobRunStatisticsModel> _job_runs;
+ private bool _loaded;
+
+ #region Properties
+ private LabeledSeriesCollection _timelineJobStatusSeries;
+ public LabeledSeriesCollection TimelineJobStatusSeries
+ {
+ get { return _timelineJobStatusSeries; }
+ set { _timelineJobStatusSeries = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _pieJobFailedReasons;
+ public LabeledSeriesCollection PieJobFailedReasons
+ {
+ get { return _pieJobFailedReasons; }
+ set { _pieJobFailedReasons = value; RaisePropertyChangedAuto(); }
+ }
+
+ private LabeledSeriesCollection _printPerWeekSeries;
+ public LabeledSeriesCollection PrintPerWeekSeries
+ {
+ get { return _printPerWeekSeries; }
+ set { _printPerWeekSeries = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _startDate;
+ public DateTime StartDate
+ {
+ get { return _startDate; }
+ set { _startDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
+ }
+
+ private DateTime _endDate;
+ public DateTime EndDate
+ {
+ get { return _endDate; }
+ set { _endDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
+ }
+
+ private DateTime _minDate;
+ public DateTime MinDate
+ {
+ get { return _minDate; }
+ set { _minDate = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _maxDate;
+ public DateTime MaxDate
+ {
+ get { return _maxDate; }
+ set { _maxDate = value; RaisePropertyChangedAuto(); }
+ }
+ #endregion
+
+ public ChartsViewVM(INotificationProvider notificationProvider)
+ {
+ _notification = notificationProvider;
+ StartDate = DateTime.Now.AddMonths(-1);
+ EndDate = DateTime.Now;
+ }
+
+ #region Generate Charts
+
+ public async void Init()
+ {
+ using (_notification.PushTaskItem("Loading statistics..."))
+ {
+ IsFree = false;
+
+ await Task.Factory.StartNew(() =>
+ {
+ _context = ObservablesContext.CreateDefault();
+ _job_runs = _context.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunStatisticsModel(x)).ToList();
+ foreach (var run in _job_runs)
+ {
+ run.LoadMachine(_context).GetAwaiter().GetResult();
+ }
+ });
+
+ if (_job_runs.Count > 0)
+ {
+ MinDate = _job_runs.Min(x => x.StartDate);
+ MaxDate = _job_runs.Max(x => x.StartDate);
+ }
+
+ InvokeUIOnIdle(() =>
+ {
+ if (_loaded)
+ {
+ OnDateRangeChanged();
+ }
+ });
+
+ _loaded = true;
+ IsFree = true;
+ }
+ }
+
+ private List<JobRunStatisticsModel> GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null)
+ {
+ return _job_runs.Where(x => x.StartDate.ToLocalTime() >= startDate && x.StartDate.ToLocalTime() <= endTime && (status == null || x.JobRunStatus == status)).ToList();
+ }
+
+ private List<JobRunStatisticsModel> GetJobRunsByDate(DateTime date, JobRunStatus? status = null)
+ {
+ return _job_runs.Where(x => x.StartDate.ToLocalTime().Date == date.Date && (status == null || x.JobRunStatus == status)).ToList();
+ }
+
+ private IEnumerable<DateTime> CreateDates(DateTime start, DateTime end)
+ {
+ for (DateTime date = start.Date; date.Date <= end.Date; date = date.AddDays(1))
+ {
+ yield return date;
+ }
+ }
+
+ private void GenerateTimelineJobStatusChart()
+ {
+ TimelineJobStatusSeries = new LabeledSeriesCollection()
+ {
+ Title = "Job Runs Status",
+ ChartTitle = "Number Of Runs",
+ LabelsTitle = "Date",
+ SeriesColors = new List<Color>()
+ {
+ Colors.Green,
+ Colors.Orange,
+ Colors.Red,
+ },
+ };
+
+ Series completed_job_runs = new ColumnSeries()
+ {
+ Title = "Completed",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Green,
+ MinWidth = 1,
+
+ };
+ Series aborted_job_runs = new ColumnSeries()
+ {
+ Title = "Aborted",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Orange,
+ MinWidth = 1,
+ };
+ Series failed_job_runs = new ColumnSeries()
+ {
+ Title = "Failed",
+ Values = new ChartValues<int>(),
+ Fill = Brushes.Red,
+ MinWidth = 1,
+ };
+
+ if (EndDate - StartDate > TimeSpan.FromDays(40))
+ {
+ completed_job_runs = new LineSeries()
+ {
+ Title = "Completed",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Green) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+
+ };
+ aborted_job_runs = new LineSeries()
+ {
+ Title = "Aborted",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Orange) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+ };
+ failed_job_runs = new LineSeries()
+ {
+ Title = "Failed",
+ Values = new ChartValues<int>(),
+ Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.5 },
+ MinWidth = 1,
+ PointGeometry = null,
+ StrokeThickness = 0,
+ };
+ }
+
+ foreach (var date in CreateDates(StartDate, EndDate))
+ {
+ completed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Completed).Count());
+ aborted_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Aborted).Count());
+ failed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Failed).Count());
+
+ TimelineJobStatusSeries.Labels.Add(date.ToShortDateString());
+ }
+
+
+
+ TimelineJobStatusSeries.SeriesCollection.Add(failed_job_runs);
+ TimelineJobStatusSeries.SeriesCollection.Add(aborted_job_runs);
+ TimelineJobStatusSeries.SeriesCollection.Add(completed_job_runs);
+ }
+
+ private void GeneratePieFailedReasonsChart()
+ {
+ var groups = GetJobRunsByDateRange(StartDate, EndDate, JobRunStatus.Failed).GroupBy(x => x.FailedMessage).OrderBy(x => x.Count());
+
+ List<Color> colors = new List<Color>();
+
+ int max = groups.Count() > 0 ? groups.Max(x => x.Count()) : 0;
+
+ for (int i = 0; i < groups.Count(); i++)
+ {
+ int count = groups.ElementAt(i).Count();
+ double alpha = Math.Max(((double)(count) / max * 200), 20);
+ colors.Add(Color.FromArgb((byte)alpha, 200, 0, 0));
+ }
+
+ PieJobFailedReasons = new LabeledSeriesCollection()
+ {
+ Title = "Job Failure Reasons",
+ SeriesColors = colors,
+ };
+
+ int index = 0;
+
+ foreach (var group in groups)
+ {
+ int count = group.Count();
+
+ var series = new PieSeries()
+ {
+ Title = group.First().FailedMessage,
+ Values = new ChartValues<int>() { count },
+ Fill = new SolidColorBrush(colors[index++]),
+ DataLabels = true,
+ ToolTip = group.First().FailedMessage,
+ };
+
+ PieJobFailedReasons.SeriesCollection.Add(series);
+ }
+ }
+
+ private void GeneratePrintPerWeekChart()
+ {
+ List<JobRunStatisticsModel> range_job_runs = GetJobRunsByDateRange(StartDate, EndDate);
+
+ Dictionary<Machine, List<double>> weeks_print_avg = new Dictionary<Machine, List<double>>();
+
+ //Init machines weeks averages dictionary.
+ foreach (var machine in range_job_runs.Select(x => x.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid))
+ {
+ weeks_print_avg[machine] = new List<double>();
+ }
+
+ //Create all available dates
+ List<DateTime> all_dates = range_job_runs.Select(x => x.StartDate).ToList();
+
+ //get first Sunday.
+ DateTime current_sunday = all_dates.FirstOrDefault(x => x.DayOfWeek == DayOfWeek.Sunday);
+
+ if (current_sunday != null && all_dates.Count > 0)
+ {
+ //Iterate over each week starting from the earliest Sunday.
+ while (current_sunday <= all_dates.Last())
+ {
+ var week_job_runs = range_job_runs.Where(x => x.EndPosition > 10 && x.StartDate >= current_sunday && x.StartDate <= current_sunday.AddDays(7)).ToList();
+
+ foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Machine))
+ {
+ weeks_print_avg[machine_job_runs.Key].Add(machine_job_runs.Select(x => x.EndPosition).Average());
+ }
+
+ current_sunday = current_sunday.AddDays(8);
+ }
+ }
+
+ Dictionary<Machine, double> week_print_avg = new Dictionary<Machine, double>();
+
+ //Init machines week average dictionary.
+ foreach (var machine in weeks_print_avg)
+ {
+ if (machine.Value.Count > 0)
+ {
+ week_print_avg[machine.Key] = machine.Value.Average();
+ }
+ }
+
+ //Init chart series
+ PrintPerWeekSeries = new LabeledSeriesCollection()
+ {
+ Title = "Average Printed Thread Per Week (m)",
+ ChartTitle = "Average Print Per Week (m)",
+ LabelsTitle = "Date",
+ SeriesColors = new List<Color>()
+ {
+
+ },
+ };
+
+ //Init series colors intensity by number of prints.
+ double max = week_print_avg.Count > 0 ? week_print_avg.Max(x => x.Value) : 0;
+ foreach (var machine in week_print_avg)
+ {
+ double a = (machine.Value / max);
+ PrintPerWeekSeries.SeriesColors.Add(Color.FromArgb((byte)(255d * (machine.Value / max)), 0, 200, 0));
+ }
+
+ //Init columns.
+ int index = 0;
+
+ foreach (var machine in week_print_avg)
+ {
+ var series = new ColumnSeries()
+ {
+ Title = machine.Key.Name,
+ Values = new ChartValues<int>() { (int)machine.Value },
+ Fill = new SolidColorBrush(PrintPerWeekSeries.SeriesColors[index++]),
+ DataLabels = true,
+ ToolTip = machine.Key.SerialNumber,
+ };
+
+ PrintPerWeekSeries.SeriesCollection.Add(series);
+ }
+ }
+
+ #endregion
+
+ #region Filter by Date
+ public void OnDateRangeChanged()
+ {
+ if (_job_runs != null && _job_runs.Count > 0)// && _loaded)
+ {
+ GenerateTimelineJobStatusChart();
+ GeneratePieFailedReasonsChart();
+ GeneratePrintPerWeekChart();
+ }
+ }
+ #endregion
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
new file mode 100644
index 000000000..cf74071c9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs
@@ -0,0 +1,304 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.Entity;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Builders;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.Core.Commands;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Statistics.Models;
+using Tango.SharedUI;
+using Tango.SharedUI.Components;
+using Tango.AutoComplete.Editors;
+
+namespace Tango.MachineStudio.Statistics.ViewModels
+{
+ public class JobRunsViewVM : ViewModel
+ {
+ private INotificationProvider _notification;
+ private List<Machine> _allMachines;
+ private List<User> _allUsers;
+ private List<RmlModel> _rmlsModels;
+ private List<JobRun> _allJobRuns;
+
+ #region Properties
+
+ private ObservableCollection<JobRunModel> _jobRuns;
+ public ObservableCollection<JobRunModel> JobRuns
+ {
+ get { return _jobRuns; }
+ set
+ {
+ _jobRuns = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private JobRunModel _selectedJobRun = null;
+ public JobRunModel SelectedJobRun
+ {
+ get { return _selectedJobRun; }
+ set
+ {
+ _selectedJobRun = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private SelectedObjectCollection<Machine> _selectedMachines;
+ public SelectedObjectCollection<Machine> SelectedMachines
+ {
+ get { return _selectedMachines; }
+ set
+ {
+ _selectedMachines = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ 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 SelectedObjectCollection<JobSource> _jobRunSelectedSources;
+ public SelectedObjectCollection<JobSource> JobRunSelectedSources
+ {
+ get { return _jobRunSelectedSources; }
+ set { _jobRunSelectedSources = value; RaisePropertyChangedAuto(); }
+ }
+
+ private SelectedObjectCollection<JobRunStatus> _jobRunSelectedStatuses;
+ public SelectedObjectCollection<JobRunStatus> JobRunSelectedStatuses
+ {
+ get { return _jobRunSelectedStatuses; }
+ set { _jobRunSelectedStatuses = value; RaisePropertyChangedAuto(); }
+ }
+
+ public SelectedObjectCollection<bool> _isGradientSelection;
+ public SelectedObjectCollection<bool> IsGradientSelection
+ {
+ get { return _isGradientSelection; }
+ set
+ {
+ _isGradientSelection = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ private SelectedObjectCollection<RmlModel> _selectedThreads;
+ public SelectedObjectCollection<RmlModel> SelectedThreads
+ {
+ get { return _selectedThreads; }
+ set
+ {
+ _selectedThreads = value;
+ RaisePropertyChangedAuto();
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the JobRuns providers.
+ /// </summary>
+ public ISuggestionProvider JobRunsProvider { get; set; }
+
+ private JobRun _jobRun;
+ public JobRun JobRun
+ {
+ get { return _jobRun; }
+ set {
+ _jobRun = value;
+ if (_jobRun != null)
+ {
+ SelectedJobName = _jobRun.JobName;
+ }
+ RaisePropertyChangedAuto(); }
+ }
+
+ private string SelectedJobName { get; set; }
+
+
+ #endregion
+
+ public RelayCommand LoadJobRunsCommand { get; set; }
+
+ public JobRunsViewVM(INotificationProvider notificationProvider)
+ {
+ _notification = notificationProvider;
+ JobRuns = new ObservableCollection<JobRunModel>();
+ LoadJobRunsCommand = new RelayCommand(async () => await LoadJobRuns(), ()=> IsFree);
+ LengthUpperValue = 5000.0;
+ LengthLowerValue = 0.0;
+ DateTime now = DateTime.Now;
+ StartSelectedDate = now.AddMonths(-1);
+ EndSelectedDate = now;
+
+ JobRunSelectedSources = new SelectedObjectCollection<JobSource>(new ObservableCollection<JobSource>()
+ {
+ JobSource.Local,
+ JobSource.Remote
+ }, new ObservableCollection<JobSource>()
+ {
+ JobSource.Local,
+ JobSource.Remote
+ });
+ JobRunSelectedSources.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(JobRunSelectedSources));
+ JobRunSelectedSources.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(JobRunSelectedSources));
+
+ JobRunSelectedStatuses = new SelectedObjectCollection<JobRunStatus>(new ObservableCollection<JobRunStatus>()
+ {
+ JobRunStatus.Aborted,
+ JobRunStatus.Completed,
+ JobRunStatus.Failed,
+
+ }, new ObservableCollection<JobRunStatus>()
+ {
+ JobRunStatus.Aborted,
+ JobRunStatus.Completed,
+ JobRunStatus.Failed,
+
+ });
+ JobRunSelectedStatuses.SelectionChanged -= (x,y)=> RaisePropertyChanged(nameof(JobRunSelectedStatuses));
+ JobRunSelectedStatuses.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(JobRunSelectedStatuses));
+
+ IsGradientSelection = new SelectedObjectCollection<bool>(new ObservableCollection<bool>
+ {
+ true,
+ false
+ }, new ObservableCollection<bool>
+ {
+ true,
+ false
+ });
+ IsGradientSelection.SelectionChanged -= (x, y) => RaisePropertyChanged(nameof(IsGradientSelection));
+ IsGradientSelection.SelectionChanged += (x, y) => RaisePropertyChanged(nameof(IsGradientSelection));
+ JobRunsProvider = new SuggestionProvider((filter) =>
+ {
+ try
+ {
+ SelectedJobName = filter;
+ return _allJobRuns.Where(x => x.JobName != null && x.JobName.ToString().StartsWith(filter, StringComparison.CurrentCultureIgnoreCase)).ToList();
+ }
+ catch
+ {
+ return null;
+ }
+ });
+
+ }
+
+ public async void Init()
+ {
+ using (_notification.PushTaskItem("Loading job runs..."))
+ {
+ try
+ {
+ IsFree = false;
+
+ using (var db = ObservablesContext.CreateDefault())
+ {
+ _allJobRuns = await db.JobRuns.ToListAsync(); ;
+ _allMachines = await db.Machines.ToListAsync();
+ _allUsers = await db.Users.Include(x => x.Contact).ToListAsync();
+ _rmlsModels = await db.Rmls.Select(x=> new RmlModel(){ Name = x.Name, Guid = x.Guid}).ToListAsync();
+ SelectedMachines = new SelectedObjectCollection<Machine>(_allMachines.ToObservableCollection(), new ObservableCollection<Machine>());
+ SelectedThreads = new SelectedObjectCollection<RmlModel>(_rmlsModels.ToObservableCollection(), new ObservableCollection<RmlModel>());
+
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading job runs.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+
+ private async Task LoadJobRuns()
+ {
+ using (_notification.PushTaskItem("Loading job runs..."))
+ {
+ try
+ {
+ IsFree = false;
+
+ using (var db = ObservablesContext.CreateDefault())
+ {
+ DateTime startUtc = StartSelectedDate.ToUniversalTime();
+ TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(23, 59, 59);
+ DateTime endUtc = EndSelectedDate.ToUniversalTime() + offsetTime;
+
+ var runs = await new JobRunsCollectionBuilder(db).Set(x => x.ActualStartDate <= DbFunctions.TruncateTime(endUtc) && x.ActualStartDate >= DbFunctions.TruncateTime(startUtc.Date))
+ .WithMachines(SelectedMachines.SynchedSource.ToList())
+ .WithJobSource(JobRunSelectedSources.SynchedSource)
+ .WithJobStatus(JobRunSelectedStatuses.SynchedSource)
+ .WithGradient(IsGradientSelection.SynchedSource)
+ .Query(y => y.Where(x => (String.IsNullOrEmpty(SelectedJobName) || x.JobName.ToString().ToLower().StartsWith(SelectedJobName.ToLower()))
+ && ( x.JobLength < LengthUpperValue && x.JobLength >= LengthLowerValue)
+ ))
+ .BuildListAsync();
+
+ var modelList = runs.Select(x => new JobRunModel()
+ {
+ JobRun = x,
+ Machine = _allMachines.FirstOrDefault(y => y.Guid == x.MachineGuid),
+ User = _allUsers.SingleOrDefault(y => y.Guid == x.UserGuid),
+ }).ToList();
+
+ modelList.ForEach(x => x.Init());
+ JobRuns = modelList.ToObservableCollection();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error loading job runs.");
+ }
+ finally
+ {
+ IsFree = true;
+ }
+ }
+ }
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
index dfbfe2648..4a75a41c8 100644
--- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/MainViewVM.cs
@@ -19,349 +19,38 @@ namespace Tango.MachineStudio.Statistics.ViewModels
{
public class MainViewVM : StudioViewModel
{
- private ObservablesContext _context;
- private List<JobRunModel> _job_runs;
- private bool rendered;
private INotificationProvider _notification;
- private bool _loaded;
- private LabeledSeriesCollection _timelineJobStatusSeries;
- public LabeledSeriesCollection TimelineJobStatusSeries
+ private ChartsViewVM _chartsViewVM;
+ public ChartsViewVM ChartsViewVM
{
- get { return _timelineJobStatusSeries; }
- set { _timelineJobStatusSeries = value; RaisePropertyChangedAuto(); }
+ get { return _chartsViewVM; }
+ set { _chartsViewVM = value; RaisePropertyChangedAuto(); }
}
- private LabeledSeriesCollection _pieJobFailedReasons;
- public LabeledSeriesCollection PieJobFailedReasons
+ private JobRunsViewVM _jobRunsViewVM;
+ public JobRunsViewVM JobRunsViewVM
{
- get { return _pieJobFailedReasons; }
- set { _pieJobFailedReasons = value; RaisePropertyChangedAuto(); }
+ get { return _jobRunsViewVM; }
+ set { _jobRunsViewVM = value; RaisePropertyChangedAuto(); }
}
-
- private LabeledSeriesCollection _printPerWeekSeries;
- public LabeledSeriesCollection PrintPerWeekSeries
- {
- get { return _printPerWeekSeries; }
- set { _printPerWeekSeries = value; RaisePropertyChangedAuto(); }
- }
-
- private DateTime _startDate;
- public DateTime StartDate
- {
- get { return _startDate; }
- set { _startDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
- }
-
- private DateTime _endDate;
- public DateTime EndDate
- {
- get { return _endDate; }
- set { _endDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); }
- }
-
- private DateTime _minDate;
- public DateTime MinDate
- {
- get { return _minDate; }
- set { _minDate = value; RaisePropertyChangedAuto(); }
- }
-
- private DateTime _maxDate;
- public DateTime MaxDate
- {
- get { return _maxDate; }
- set { _maxDate = value; RaisePropertyChangedAuto(); }
- }
-
+
public MainViewVM(INotificationProvider notificationProvider)
{
_notification = notificationProvider;
-
- StartDate = DateTime.Now.AddMonths(-1);
- EndDate = DateTime.Now;
+ ChartsViewVM = new ChartsViewVM(_notification);
+ JobRunsViewVM = new JobRunsViewVM(_notification);
}
public override void OnApplicationReady()
{
-
- }
-
- private List<JobRunModel> GetJobRunsByDateRange(DateTime startDate, DateTime endTime, JobRunStatus? status = null)
- {
- return _job_runs.Where(x => x.StartDate.ToLocalTime() >= startDate && x.StartDate.ToLocalTime() <= endTime && (status == null || x.JobRunStatus == status)).ToList();
- }
-
- private List<JobRunModel> GetJobRunsByDate(DateTime date, JobRunStatus? status = null)
- {
- return _job_runs.Where(x => x.StartDate.ToLocalTime().Date == date.Date && (status == null || x.JobRunStatus == status)).ToList();
- }
-
- private IEnumerable<DateTime> CreateDates(DateTime start, DateTime end)
- {
- for (DateTime date = start.Date; date.Date <= end.Date; date = date.AddDays(1))
- {
- yield return date;
- }
+ JobRunsViewVM.Init();
}
- public override async void OnNavigatedTo()
+ public override void OnNavigatedTo()
{
base.OnNavigatedTo();
-
- if (rendered) return;
-
- rendered = true;
-
-
- using (_notification.PushTaskItem("Loading statistics..."))
- {
- IsFree = false;
-
- await Task.Factory.StartNew(() =>
- {
- _context = ObservablesContext.CreateDefault();
- _job_runs = _context.JobRuns.OrderBy(x => x.StartDate).ToList().Select(x => new JobRunModel(x)).ToList();
- foreach (var run in _job_runs)
- {
- run.LoadMachine(_context).GetAwaiter().GetResult();
- }
- });
-
- if (_job_runs.Count > 0)
- {
- MinDate = _job_runs.Min(x => x.StartDate);
- MaxDate = _job_runs.Max(x => x.StartDate);
- }
-
- InvokeUIOnIdle(() =>
- {
- OnDateRangeChanged();
- });
-
- _loaded = true;
-
- IsFree = true;
- }
- }
-
- private void OnDateRangeChanged()
- {
- if (_job_runs != null && _job_runs.Count > 0 && _loaded)
- {
- GenerateTimelineJobStatusChart();
- GeneratePieFailedReasonsChart();
- GeneratePrintPerWeekChart();
- }
- }
-
- private void GenerateTimelineJobStatusChart()
- {
- TimelineJobStatusSeries = new LabeledSeriesCollection()
- {
- Title = "Job Runs Status",
- ChartTitle = "Number Of Runs",
- LabelsTitle = "Date",
- SeriesColors = new List<Color>()
- {
- Colors.Green,
- Colors.Orange,
- Colors.Red,
- },
- };
-
- Series completed_job_runs = new ColumnSeries()
- {
- Title = "Completed",
- Values = new ChartValues<int>(),
- Fill = Brushes.Green,
- MinWidth = 1,
-
- };
- Series aborted_job_runs = new ColumnSeries()
- {
- Title = "Aborted",
- Values = new ChartValues<int>(),
- Fill = Brushes.Orange,
- MinWidth = 1,
- };
- Series failed_job_runs = new ColumnSeries()
- {
- Title = "Failed",
- Values = new ChartValues<int>(),
- Fill = Brushes.Red,
- MinWidth = 1,
- };
-
- if (EndDate - StartDate > TimeSpan.FromDays(40))
- {
- completed_job_runs = new LineSeries()
- {
- Title = "Completed",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Green) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
-
- };
- aborted_job_runs = new LineSeries()
- {
- Title = "Aborted",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Orange) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
- };
- failed_job_runs = new LineSeries()
- {
- Title = "Failed",
- Values = new ChartValues<int>(),
- Fill = new SolidColorBrush(Colors.Red) { Opacity = 0.5 },
- MinWidth = 1,
- PointGeometry = null,
- StrokeThickness = 0,
- };
- }
-
- foreach (var date in CreateDates(StartDate, EndDate))
- {
- completed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Completed).Count());
- aborted_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Aborted).Count());
- failed_job_runs.Values.Add(GetJobRunsByDate(date, JobRunStatus.Failed).Count());
-
- TimelineJobStatusSeries.Labels.Add(date.ToShortDateString());
- }
-
-
-
- TimelineJobStatusSeries.SeriesCollection.Add(failed_job_runs);
- TimelineJobStatusSeries.SeriesCollection.Add(aborted_job_runs);
- TimelineJobStatusSeries.SeriesCollection.Add(completed_job_runs);
- }
-
- private void GeneratePieFailedReasonsChart()
- {
- var groups = GetJobRunsByDateRange(StartDate, EndDate, JobRunStatus.Failed).GroupBy(x => x.FailedMessage).OrderBy(x => x.Count());
-
- List<Color> colors = new List<Color>();
-
- int max = groups.Count() > 0 ? groups.Max(x => x.Count()) : 0;
-
- for (int i = 0; i < groups.Count(); i++)
- {
- int count = groups.ElementAt(i).Count();
- double alpha = Math.Max(((double)(count) / max * 200), 20);
- colors.Add(Color.FromArgb((byte)alpha, 200, 0, 0));
- }
-
- PieJobFailedReasons = new LabeledSeriesCollection()
- {
- Title = "Job Failure Reasons",
- SeriesColors = colors,
- };
-
- int index = 0;
-
- foreach (var group in groups)
- {
- int count = group.Count();
-
- var series = new PieSeries()
- {
- Title = group.First().FailedMessage,
- Values = new ChartValues<int>() { count },
- Fill = new SolidColorBrush(colors[index++]),
- DataLabels = true,
- ToolTip = group.First().FailedMessage,
- };
-
- PieJobFailedReasons.SeriesCollection.Add(series);
- }
- }
-
- private void GeneratePrintPerWeekChart()
- {
- List<JobRunModel> range_job_runs = GetJobRunsByDateRange(StartDate, EndDate);
-
- Dictionary<Machine, List<double>> weeks_print_avg = new Dictionary<Machine, List<double>>();
-
- //Init machines weeks averages dictionary.
- foreach (var machine in range_job_runs.Select(x => x.Machine).OrderBy(x => x.Name).DistinctBy(x => x.Guid))
- {
- weeks_print_avg[machine] = new List<double>();
- }
-
- //Create all available dates
- List<DateTime> all_dates = range_job_runs.Select(x => x.StartDate).ToList();
-
- //get first Sunday.
- DateTime current_sunday = all_dates.FirstOrDefault(x => x.DayOfWeek == DayOfWeek.Sunday);
-
- if (current_sunday != null && all_dates.Count > 0)
- {
- //Iterate over each week starting from the earliest Sunday.
- while (current_sunday <= all_dates.Last())
- {
- var week_job_runs = range_job_runs.Where(x => x.EndPosition > 10 && x.StartDate >= current_sunday && x.StartDate <= current_sunday.AddDays(7)).ToList();
-
- foreach (var machine_job_runs in week_job_runs.GroupBy(x => x.Machine))
- {
- weeks_print_avg[machine_job_runs.Key].Add(machine_job_runs.Select(x => x.EndPosition).Average());
- }
-
- current_sunday = current_sunday.AddDays(8);
- }
- }
-
- Dictionary<Machine, double> week_print_avg = new Dictionary<Machine, double>();
-
- //Init machines week average dictionary.
- foreach (var machine in weeks_print_avg)
- {
- if (machine.Value.Count > 0)
- {
- week_print_avg[machine.Key] = machine.Value.Average();
- }
- }
-
- //Init chart series
- PrintPerWeekSeries = new LabeledSeriesCollection()
- {
- Title = "Average Printed Thread Per Week (m)",
- ChartTitle = "Average Print Per Week (m)",
- LabelsTitle = "Date",
- SeriesColors = new List<Color>()
- {
-
- },
- };
-
- //Init series colors intensity by number of prints.
- double max = week_print_avg.Count > 0 ? week_print_avg.Max(x => x.Value) : 0;
- foreach (var machine in week_print_avg)
- {
- double a = (machine.Value / max);
- PrintPerWeekSeries.SeriesColors.Add(Color.FromArgb((byte)(255d * (machine.Value / max)), 0, 200, 0));
- }
-
- //Init columns.
- int index = 0;
-
- foreach (var machine in week_print_avg)
- {
- var series = new ColumnSeries()
- {
- Title = machine.Key.Name,
- Values = new ChartValues<int>() { (int)machine.Value },
- Fill = new SolidColorBrush(PrintPerWeekSeries.SeriesColors[index++]),
- DataLabels = true,
- ToolTip = machine.Key.SerialNumber,
- };
-
- PrintPerWeekSeries.SeriesCollection.Add(series);
- }
+ ChartsViewVM.Init();
}
}
}