diff options
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels')
3 files changed, 325 insertions, 1107 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 deleted file mode 100644 index a98257086..000000000 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/ChartsViewVM.cs +++ /dev/null @@ -1,364 +0,0 @@ -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; -using Tango.Core.Commands; - -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(); RaisePropertyChanged("EndDate"); } - } - - private DateTime _endDate; - public DateTime EndDate - { - get { return _endDate; } - set { _endDate = value; RaisePropertyChangedAuto(); RaisePropertyChanged("StartDate"); } - } - - public RelayCommand LoadJobRunsCommand { get; set; } - #endregion - - public ChartsViewVM(INotificationProvider notificationProvider) - { - _notification = notificationProvider; - StartDate = DateTime.Now.AddMonths(-1); - EndDate = DateTime.Now; - LoadJobRunsCommand = new RelayCommand(async () => await LoadJobRuns(), () => IsFree); - } - - #region Generate Charts - - private async Task LoadJobRuns() - { - using (_notification.PushTaskItem("Loading statistics...")) - { - try - { - IsFree = false; - - await Task.Factory.StartNew(() => - { - using (var db = ObservablesContext.CreateDefault()) - { - DateTime startUtc = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, 0, 0, 0).ToUniversalTime(); - TimeSpan offsetTime = (EndDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(23, 59, 59); - DateTime endUtc = EndDate.ToUniversalTime() + offsetTime; - - _job_runs = db.JobRuns.Where(x => (x.StartDate <= endUtc && x.StartDate >= startUtc)).OrderBy(x => x.StartDate).ToList().Select(x => new JobRunStatisticsModel(x)).ToList(); - - foreach (var run in _job_runs) - { - run.LoadMachine(db).GetAwaiter().GetResult(); - } - } - }); - - InvokeUIOnIdle(() => - { - if (_loaded) - { - OnDateRangeChanged(); - } - }); - - _loaded = true; - } - catch (Exception ex) - { - LogManager.Log(ex, "Error loading statistics."); - } - finally - { - 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 deleted file mode 100644 index ae1592d8d..000000000 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Statistics/ViewModels/JobRunsViewVM.cs +++ /dev/null @@ -1,729 +0,0 @@ -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; -using System.Windows.Media; -using LiveCharts.Wpf; -using LiveCharts; -using Tango.BL.ValueObjects; -using System.Diagnostics; -using Microsoft.Win32; -using Tango.CSV; -using System.ComponentModel; - -namespace Tango.MachineStudio.Statistics.ViewModels -{ - public enum HeadCleaningSelectionEnum - { - [Description("Exclude")] - Exclude = 0, - [Description("Include")] - Include = 1, - [Description("Only")] - Only = 2 - }; - - - public class JobRunsViewVM : ViewModel - { - private INotificationProvider _notification; - private List<Machine> _allMachines; - private List<User> _allUsers; - private List<RmlModel> _rmlsModels; - - - - #region Properties - - private ObservableCollection<JobRunModel> _jobRuns; - /// <summary> - /// Gets or sets the job runs. Contains filtered data of JobRunModel. - /// </summary> - public ObservableCollection<JobRunModel> JobRuns - { - get { return _jobRuns; } - set - { - _jobRuns = value; - RaisePropertyChangedAuto(); - } - } - - private JobRunModel _selectedJobRun = null; - /// <summary> - /// Gets or sets the JobRunModel. Binding to selected item of grid items. - /// </summary> - public JobRunModel SelectedJobRun - { - get { return _selectedJobRun; } - set - { - _selectedJobRun = value; - RaisePropertyChangedAuto(); - } - } - - private SelectedObjectCollection<Machine> _selectedMachines; - /// <summary> - /// Gets or sets the selected machines. Contains all available machines and selected machines. Binding to ComboBox Machines. - /// </summary> - public SelectedObjectCollection<Machine> SelectedMachines - { - get { return _selectedMachines; } - set - { - _selectedMachines = value; - RaisePropertyChangedAuto(); - } - } - - private DateTime _startSelectedDate; - /// <summary> - /// Gets or sets the start selected date. - /// </summary> - public DateTime StartSelectedDate - { - get { return _startSelectedDate; } - set { _startSelectedDate = value; - RaisePropertyChangedAuto(); - } - } - - private DateTime _endSelectedDate; - /// <summary> - /// Gets or sets the end selected date. - /// </summary> - public DateTime EndSelectedDate - { - get { return _endSelectedDate; } - set { _endSelectedDate = value; RaisePropertyChangedAuto(); } - } - - protected Double _lengthLowerValue; - /// <summary> - /// Gets or sets the length lower value of Range Slider - /// </summary> - public Double LengthLowerValue - { - get { return _lengthLowerValue; } - set - { - _lengthLowerValue = value; - RaisePropertyChangedAuto(); - } - } - - protected Double _lengthUpperValue; - /// <summary> - /// Gets or sets the length upper value of Range Slider. - /// </summary> - public Double LengthUpperValue - { - get { return _lengthUpperValue; } - set - { - _lengthUpperValue = value; - RaisePropertyChangedAuto(); - } - } - - private SelectedObjectCollection<JobSource> _jobRunSelectedSources; - /// <summary> - /// Gets or sets the job run selected sources. Binding to ComboBox "Source". - /// </summary> - public SelectedObjectCollection<JobSource> JobRunSelectedSources - { - get { return _jobRunSelectedSources; } - set { _jobRunSelectedSources = value; RaisePropertyChangedAuto(); } - } - - private SelectedObjectCollection<JobRunStatus> _jobRunSelectedStatuses; - /// <summary> - /// Gets or sets the job run selected statuses. Binding to ComboBox "Status". - /// </summary> - public SelectedObjectCollection<JobRunStatus> JobRunSelectedStatuses - { - get { return _jobRunSelectedStatuses; } - set { _jobRunSelectedStatuses = value; RaisePropertyChangedAuto(); } - } - - public SelectedObjectCollection<bool> _isGradientSelection; - /// <summary> - /// Gets or sets the is gradient selection. Binding to ComboBox "IsGradient". - /// </summary> - public SelectedObjectCollection<bool> IsGradientSelection - { - get { return _isGradientSelection; } - set - { - _isGradientSelection = value; - RaisePropertyChangedAuto(); - } - } - - private SelectedObjectCollection<RmlModel> _selectedThreads; - /// <summary> - /// Gets or sets the selected threads. Contains all available threads and selected threads. Binding to ComboBox "Thread". - /// </summary> - public SelectedObjectCollection<RmlModel> SelectedThreads - { - get { return _selectedThreads; } - set - { - _selectedThreads = value; - RaisePropertyChangedAuto(); - } - } - - private HeadCleaningSelectionEnum _headCleaningSelected; - - public HeadCleaningSelectionEnum HeadCleaningSelected - { - get { return _headCleaningSelected; } - set - { - _headCleaningSelected = value; - RaisePropertyChangedAuto(); - } - } - - - /// <summary> - /// Gets or sets the JobRuns providers. - /// </summary> - public ISuggestionProvider JobsProvider { get; set; } - - private Job _selectedJob; - /// <summary> - /// Gets or sets the job. - /// </summary> - public Job SelectedJob - { - get { return _selectedJob; } - set - { - _selectedJob = value; - RaisePropertyChangedAuto(); - } - } - - /// <summary> - /// Gets or sets the statistics value collection. Class - container included calculated statistic values. - /// </summary> - public StatisticsValueCollection StatisticsValueCollection { get; set; } - - #endregion - - public RelayCommand LoadJobRunsCommand { get; set; } - - public RelayCommand ExportToExcelCommand { get; set; } - - public JobRunsViewVM(INotificationProvider notificationProvider) - { - _notification = notificationProvider; - JobRuns = new ObservableCollection<JobRunModel>(); - LoadJobRunsCommand = new RelayCommand(async () => await LoadJobRuns(), () => IsFree); - ExportToExcelCommand = new RelayCommand(ExportToExcel, () => IsFree); - LengthUpperValue = 10000.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)); - - HeadCleaningSelected = HeadCleaningSelectionEnum.Exclude; - - JobsProvider = new SuggestionProvider((filter) => - { - try - { - if (filter != null) - { - using (ObservablesContext db = ObservablesContext.CreateDefault()) - { - return db.Jobs.Where(x => x.Name != null && x.Name.ToLower().Contains(filter.ToLower())).ToList(); - } - } - else - { - return new List<Job>(); - } - } - catch (Exception ex) - { - LogManager.Log(ex, "Error loading jobs."); - return null; - } - }); - - StatisticsValueCollection = new StatisticsValueCollection(); - } - - /// <summary> - /// Initializes this instance. Called form main view VM in OnApplicationReady - /// </summary> - public async void Init() - { - using (_notification.PushTaskItem("Loading job runs...")) - { - try - { - IsFree = false; - - using (var db = ObservablesContext.CreateDefault()) - { - _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; - } - } - - } - - /// <summary> - /// Loads the job runs by filters. - /// </summary> - private async Task LoadJobRuns() - { - using (_notification.PushTaskItem("Loading job runs...")) - { - try - { - IsFree = false; - - using (var db = ObservablesContext.CreateDefault()) - { - DateTime startUtc = new DateTime(StartSelectedDate.Year, StartSelectedDate.Month, StartSelectedDate.Day, 0, 0, 0).ToUniversalTime(); - TimeSpan offsetTime = (EndSelectedDate.Date == DateTime.Now.Date) ? DateTime.Now.TimeOfDay : new TimeSpan(23, 59, 59); - DateTime endUtc = EndSelectedDate.ToUniversalTime() + offsetTime; - - string jobName = SelectedJob == null ? "" : SelectedJob.Name; - - var db_JobRuns = db.JobRuns.Where(x => (x.StartDate <= endUtc && x.StartDate >= startUtc)) - .Select(x => new - { - x.ID, - x.ActualStartDate, - x.EndDate, - x.EndPosition, - x.GradientResolutionCm, - x.Guid, - x.HeatingStartDate, - x.IsGradient, - x.JobGuid, - x.JobLength, - x.JobName, - x.JobSource, - x.MachineGuid, - x.RmlGuid, - x.StartDate, - x.Status, - x.UploadingStartDate, - x.UserGuid, - x.CyanQuantity, - x.MagentaQuantity, - x.YellowQuantity, - x.BlackQuantity, - x.TransparentQuantity, - x.LubricantQuantity, - x.CleanerQuantity, - x.IsHeadCleaning - }); - var machineIDs = new HashSet<string>(SelectedMachines.SynchedSource.ToList().Select(p => p.Guid)); - if (machineIDs.Count > 0) - { - db_JobRuns = db_JobRuns.Where(x => machineIDs.Contains(x.MachineGuid)); - } - int[] jobRunSourceArr = JobRunSelectedSources.SynchedSource.Select(x => (int)x).ToArray(); - if (jobRunSourceArr.Length > 0) - { - db_JobRuns = db_JobRuns.Where(x => jobRunSourceArr.Contains(x.JobSource)); - } - int[] jobRunStatusArr = JobRunSelectedStatuses.SynchedSource.Select(x => (int)x).ToArray(); - if (jobRunStatusArr.Length > 0) - { - db_JobRuns = db_JobRuns.Where(x => jobRunStatusArr.Contains(x.Status)); - } - bool[] isGradientArr = IsGradientSelection.SynchedSource.Select(x => (bool)x).ToArray(); - if (isGradientArr.Length > 0) - { - db_JobRuns = db_JobRuns.Where(x => isGradientArr.Contains(x.IsGradient)); - } - - if(HeadCleaningSelected != HeadCleaningSelectionEnum.Include) - { - bool isHeadCleaning = HeadCleaningSelected == HeadCleaningSelectionEnum.Only; - db_JobRuns = db_JobRuns.Where(x => isHeadCleaning == x.IsHeadCleaning); - } - - List<String> rmlGuids = SelectedThreads.SynchedSource.Select(y => y.Guid).ToList(); - if (rmlGuids != null && rmlGuids.Count > 0) - { - db_JobRuns = db_JobRuns.Where(x => rmlGuids.Contains(x.RmlGuid)); - } - if (!String.IsNullOrEmpty(jobName)) - { - db_JobRuns = db_JobRuns.Where(x => x.JobName.ToLower().StartsWith(jobName.ToLower())); - } - - var runs_db = await db_JobRuns.ToListAsync(); //Execute actual query. - - - List<JobRun> runs = runs_db.Where(x => (x.JobLength < LengthUpperValue && x.JobLength >= LengthLowerValue)) - .Select(x => new JobRun() - { - ID = x.ID, - ActualStartDate = x.ActualStartDate, - EndDate = x.EndDate, - EndPosition = x.EndPosition, - GradientResolutionCm = x.GradientResolutionCm, - Guid = x.Guid, - HeatingStartDate = x.HeatingStartDate, - IsGradient = x.IsGradient, - JobGuid = x.JobGuid, - JobLength = x.JobLength, - JobName = x.JobName, - JobSource = x.JobSource, - MachineGuid = x.MachineGuid, - RmlGuid = x.RmlGuid, - StartDate = x.StartDate, - Status = x.Status, - UploadingStartDate = x.UploadingStartDate, - UserGuid = x.UserGuid, - CyanQuantity = x.CyanQuantity, - MagentaQuantity = x.MagentaQuantity, - YellowQuantity = x.YellowQuantity, - BlackQuantity = x.BlackQuantity, - TransparentQuantity = x.TransparentQuantity, - LubricantQuantity = x.LubricantQuantity, - CleanerQuantity = x.CleanerQuantity, - IsHeadCleaning = x.IsHeadCleaning - }).ToList(); - - 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), - Rml = _rmlsModels.SingleOrDefault(y => y.Guid == x.RmlGuid), - }).OrderByDescending(x => x.JobRun.StartDate).ToList(); - - modelList.ForEach(x => x.Init()); - JobRuns = modelList.ToObservableCollection(); - GenerateStatistics(); - } - - - } - catch (Exception ex) - { - LogManager.Log(ex, "Error loading job runs."); - } - finally - { - IsFree = true; - } - } - } - - private void ExportToExcel() - { - SaveFileDialog dlg = new SaveFileDialog(); - dlg.Title = "Job Runs Statistic Report"; - dlg.Filter = "CSV Files|*.csv"; - dlg.FileName = $"Statistics_Job_runs"; - dlg.DefaultExt = ".csv"; - if (dlg.ShowDialog().Value) - { - try - { - CsvFile<ExcelModel> csvFile = new CsvFile<ExcelModel>(new CsvDestination(dlg.FileName), new CsvDefinition() - { - Columns = new List<String>() - { - "ID", - "Machine", - "User", - "Job Name", - "Thread", - "Length", - "Source", - "Upload Duration", - "Heating Duration", - "Start Time", - "IsGradient", - "Gradient Resolution", - "Status", - "End Date", - "End Position", - "Cyan", - "Magenta", - "Yellow", - "Black", - "Transparent", - "Lubricant", - "Cleaner" - }, - }); - var selection = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.EndDate != null && z.JobRun.ActualStartDate != null); - foreach (var jobRunModel in selection) - { - ExcelModel excel_model = new ExcelModel(); - excel_model.ID = jobRunModel.JobRun.ID.ToString(); - excel_model.Machine = jobRunModel.Machine != null ? jobRunModel.Machine.SerialNumber : ""; - excel_model.User = jobRunModel.User != null ? jobRunModel.User.Contact.FullName: ""; - excel_model.JobName = jobRunModel.JobRun.JobName; - excel_model.Thread = jobRunModel.Rml != null ? jobRunModel.Rml.Name : ""; - excel_model.Length = String.Format("{0:0.##}", jobRunModel.JobRun.JobLength); - excel_model.Source = jobRunModel.JobRun.Source.ToString(); - excel_model.UploadDuration = jobRunModel.UploadDuration != null ? ((TimeSpan)(jobRunModel.UploadDuration)).ToString(@"hh\:mm\:ss") : TimeSpan.FromSeconds(0).ToString(@"hh\:mm\:ss"); - excel_model.HeatingDuration = jobRunModel.HeatingDuration != null ? ((TimeSpan)(jobRunModel.HeatingDuration)).ToString(@"hh\:mm\:ss") : TimeSpan.FromSeconds(0).ToString(@"hh\:mm\:ss"); - excel_model.StartTime = jobRunModel.JobRun.ActualStartDate != null ? ((DateTime)jobRunModel.JobRun.ActualStartDate).ToLocalTime().ToString("MM/dd/yy HH:mm"): ""; - excel_model.IsGradient = jobRunModel.JobRun.IsGradient ? "Yes" : "No"; - excel_model.GR = jobRunModel.JobRun.GradientResolutionCm.ToString(); - excel_model.Status = jobRunModel.JobRun.JobRunStatus.ToString(); - excel_model.EndTime = jobRunModel.JobRun.EndDate != null ? ((DateTime)jobRunModel.JobRun.EndDate).ToLocalTime().ToString("MM/dd/yy HH:mm"): ""; - excel_model.EndPosition = String.Format("{0:0.##}", jobRunModel.JobRun.EndPosition); - excel_model.Cyan = jobRunModel.JobRun.CyanQuantity < 0 ? "" :jobRunModel.JobRun.CyanQuantity.ToString(); - excel_model.Magenta = jobRunModel.JobRun.MagentaQuantity < 0 ? "" : jobRunModel.JobRun.MagentaQuantity.ToString(); - excel_model.Yellow = jobRunModel.JobRun.YellowQuantity < 0 ? "" : jobRunModel.JobRun.YellowQuantity.ToString(); - excel_model.Black = jobRunModel.JobRun.BlackQuantity < 0 ? "" : jobRunModel.JobRun.BlackQuantity.ToString(); - excel_model.Transparent = jobRunModel.JobRun.TransparentQuantity < 0 ? "" : jobRunModel.JobRun.TransparentQuantity.ToString(); - excel_model.Lubricant = jobRunModel.JobRun.LubricantQuantity < 0 ? "" : jobRunModel.JobRun.LubricantQuantity.ToString(); - excel_model.Cleaner = jobRunModel.JobRun.CleanerQuantity < 0 ? "" : jobRunModel.JobRun.CleanerQuantity.ToString(); - csvFile.Append(excel_model); - - } - - csvFile.Dispose(); - _notification.ShowInfo("Report generated successfully."); - } - catch (Exception ex) - { - LogManager.Log(ex, "Error generating Statistics Job Runs report."); - _notification.ShowError($"Error generating Statistics Job Runs report..\n{ex.Message}"); - } - } - } - #region GenerateS_StatisticsValueCollection - - /// <summary> - /// Generates the statistics. - /// </summary> - protected void GenerateStatistics() - { - StatisticsValueCollection.Clean(); - if (JobRuns.Count() == 0) - return; - GenerateTotalRunsCount(); - GenerateTotalRunsLength(); - GenerateTotalThreadConsumption(); - GenerateRunsDuration(); - GenerateAverageUploadDuration(); - GenerateAverageHeatingDuration(); - - GeneratePieCharts(); - CreateThreadConsumptionPerThread(); - GenerateAllLiquidQuantities(); - } - - protected void GenerateTotalRunsCount() - {//Total Runs: - int val = JobRuns.Count(); - StatisticsValueCollection.AddStatisticsValue("Total Runs ", val, " "); - } - - /// <summary> - /// Generates the total length of the job runs. - /// </summary> - protected void GenerateTotalRunsLength() - { - double val = JobRuns.Where(z => z.JobRun.EndPosition > 0).Sum(x => x.JobRun.JobLength); - StatisticsValueCollection.AddStatisticsValue("Total Runs Length", val, " m"); - } - - /// <summary> - /// Generates the duration and average of the job runs. - /// </summary> - protected void GenerateRunsDuration() - { - var selection = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.EndDate != null && z.JobRun.ActualStartDate != null); - double val = 0d; - double average = 0d; - if (selection != null && selection.Count<JobRunModel>() > 0) - { - val = selection.Sum(x => (x.JobRun.EndDate - x.JobRun.ActualStartDate).Value.TotalHours); - average = selection.Average(x => (x.JobRun.EndDate - x.JobRun.ActualStartDate).Value.TotalMilliseconds); - } - StatisticsValueCollection.AddStatisticsValue("Total Dyeing Time", val, " hours"); - StatisticsValueCollection.AddStatisticsValue("Average Dyeing Time", Math.Max(TimeSpan.FromMilliseconds(average).TotalHours, 0), " hours"); - } - - /// <summary> - /// Generates the average upload duration of the job runs. - /// </summary> - protected void GenerateAverageUploadDuration() - { - var average = (long)JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.UploadDuration != null).Average(x => x.UploadDuration.Value.TotalMilliseconds); - StatisticsValueCollection.AddStatisticsValue("Average Upload Duration", Math.Max(TimeSpan.FromMilliseconds(average).TotalMinutes, 0), " minutes"); - } - - /// <summary> - /// Generates the average duration heating of the job runs. - /// </summary> - protected void GenerateAverageHeatingDuration() - { - var average = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.HeatingDuration != null && z.HeatingDuration.Value.Ticks > 0).Average(x => x.HeatingDuration.Value.TotalMilliseconds); - StatisticsValueCollection.AddStatisticsValue("Average Heating Duration", Math.Max(TimeSpan.FromMilliseconds(average).TotalMinutes, 0), " minutes"); - } - - /// <summary> - /// Generates the total thread consumption by EndPosition. - /// </summary> - protected void GenerateTotalThreadConsumption() - { - double val = JobRuns.Where(z => z.JobRun.EndPosition > 0).Sum(x => x.JobRun.EndPosition); - StatisticsValueCollection.AddStatisticsValue("Total Dyeing Length", val, " m"); - } - - /// <summary> - /// Generates the pie charts in percentage: JobSource, JobRunStatus, Gradient. - /// </summary> - protected void GeneratePieCharts() - { - int PPCCount = JobRuns.Count(x => x.JobRun.Source == JobSource.Local); - int MSCount = JobRuns.Count(x => x.JobRun.Source == JobSource.Remote); - StatisticsValueCollection.GeneratePieJobSource(PPCCount, MSCount); - - int failedCount = JobRuns.Count(x => x.JobRun.JobRunStatus == JobRunStatus.Failed); - int abortedCount = JobRuns.Count(x => x.JobRun.JobRunStatus == JobRunStatus.Aborted); - int completedCount = JobRuns.Count(x => x.JobRun.JobRunStatus == JobRunStatus.Completed); - StatisticsValueCollection.GeneratePieJobRunStatus(failedCount, abortedCount, completedCount); - - int gradientCount = JobRuns.Count(x => x.JobRun.IsGradient == true); - int solidCount = JobRuns.Count(x => x.JobRun.IsGradient == false); - StatisticsValueCollection.GeneratePieGradientSolid(gradientCount, solidCount); - - } - - /// <summary> - /// Creates the thread consumption per thread. - /// </summary> - protected void CreateThreadConsumptionPerThread() - { - var temp = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.Rml != null).GroupBy(x => x.Rml.Name); - List<StatisticsValue> result = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.Rml != null && !String.IsNullOrEmpty(z.Rml.Name)).GroupBy(x => x.Rml.Name).Select(y => new StatisticsValue { Name = y.Key, Value = y.Sum(x => x.JobRun.EndPosition), Unit = "m" }).ToList(); - StatisticsValueCollection.CreateThreadConsumptionPerThread(result); - } - - /// <summary> - /// Generates all liquid quantities. - /// </summary> - protected void GenerateAllLiquidQuantities() - { - var runs = JobRuns.Where(z => z.JobRun.EndPosition > 0 && z.JobRun.LiquidQuantitiesFast.Count > 0).ToList(); - - Dictionary<LiquidTypes, ulong> total_quantities = new Dictionary<LiquidTypes, ulong>(); - - foreach (LiquidTypes ltype in (LiquidTypes[])Enum.GetValues(typeof(LiquidTypes))) - { - total_quantities[ltype] = 0; - } - - foreach (var run in runs) - { - foreach (var lq in run.JobRun.LiquidQuantitiesFast) - { - if (lq.Quantity < 0) - { - Debug.WriteLine($"Warning: JobRun '{run.JobRun.ID}' contains an invalid value '{lq.Quantity}' for {lq.LiquidType} quantity."); - } - - total_quantities[lq.LiquidType] += Convert.ToUInt64(Math.Max(lq.Quantity, 0)); - } - } - - List<TotalLiquidQuantityModel> allLiquidQuantities = total_quantities.Select(x => new TotalLiquidQuantityModel() - { - LiquidType = x.Key, - Quantity = x.Value - }).ToList(); - - - //foreach (LiquidTypes ltype in (LiquidTypes[])Enum.GetValues(typeof(LiquidTypes))) - //{ - // var liquidQuantityByTypeList = db_liquidQuantities.Select(x => x.FirstOrDefault(y => y.LiquidType == ltype)).Where(x => x != null); - // var count = liquidQuantityByTypeList != null ? liquidQuantityByTypeList.Sum(x => x.Quantity) : 0; - // JobRunLiquidQuantity lq = new JobRunLiquidQuantity() { LiquidType = ltype, Quantity = count }; - // allLiquidQuantities.Add(lq); - //} - StatisticsValueCollection.GenerateStatisticsLiquidQuantity(allLiquidQuantities); - } - #endregion - - } -} 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 e7e2013c5..ef9561d0b 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 @@ -7,49 +7,360 @@ using System.Text; using System.Threading.Tasks; using System.Windows.Media; using Tango.BL; +using Tango.BL.Entities; using Tango.BL.Enumerations; using Tango.Core.Helpers; using Tango.MachineStudio.Common; using Tango.MachineStudio.Statistics.Models; using System.Data.Entity; using Tango.MachineStudio.Common.Notifications; -using Tango.BL.Entities; namespace Tango.MachineStudio.Statistics.ViewModels { public class MainViewVM : StudioViewModel { + private ObservablesContext _context; + private List<JobRun> _job_runs; + private bool rendered; private INotificationProvider _notification; + private bool _loaded; + + 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 ChartsViewVM _chartsViewVM; - public ChartsViewVM ChartsViewVM + private DateTime _startDate; + public DateTime StartDate { - get { return _chartsViewVM; } - set { _chartsViewVM = value; RaisePropertyChangedAuto(); } + get { return _startDate; } + set { _startDate = value; RaisePropertyChangedAuto(); OnDateRangeChanged(); } } - private JobRunsViewVM _jobRunsViewVM; - public JobRunsViewVM JobRunsViewVM + private DateTime _endDate; + public DateTime EndDate { - get { return _jobRunsViewVM; } - set { _jobRunsViewVM = value; RaisePropertyChangedAuto(); } + 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; - ChartsViewVM = new ChartsViewVM(_notification); - JobRunsViewVM = new JobRunsViewVM(_notification); + + StartDate = DateTime.Now.AddMonths(-1); + EndDate = DateTime.Now; } public override void OnApplicationReady() { - JobRunsViewVM.Init(); + } - public override void OnNavigatedTo() + private List<JobRun> 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<JobRun> 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; + } + } + + + + public override async 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.Include(x => x.Job).Include(x => x.Job.Machine).OrderBy(x => x.StartDate).ToList(); + }); + + 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<JobRun> 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.Job.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.Job.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); + } } } } |
