using Microsoft.Win32; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Reflection; 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.CSV; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.HardwareDesigner.Comparison; using Tango.MachineStudio.HardwareDesigner.Report; using Tango.SharedUI; namespace Tango.MachineStudio.HardwareDesigner.ViewModels { /// /// class ComparisonWizardViewVM is view model of dialog for compare properties of 2 hardware versions /// /// public class ComparisonWizardViewVM : DialogViewVM { private INotificationProvider _notification; #region Properties private ObservableCollection _hardwareVersions; /// /// Gets or sets the hardware versions. Contains all available versions. /// /// /// The hardware versions. /// public ObservableCollection HardwareVersions { get { return _hardwareVersions; } set { _hardwareVersions = value; RaisePropertyChangedAuto(); } } private HardwareVersion _selectedVersion1; /// /// Gets or sets the selected version1 contains selected value from left combo box /// /// /// The selected version1. /// public HardwareVersion SelectedVersion1 { get { return _selectedVersion1; } set { if (value != null && (_selectedVersion1 == null || _selectedVersion1.Guid != value.Guid)) { _selectedVersion1 = value; RaisePropertyChangedAuto(); OnSelectedVersionChanged(); } } } private HardwareVersion _selectedVersion2; /// /// Gets or sets the selected version2 contains selected value from right combo box /// /// /// The selected version2. /// public HardwareVersion SelectedVersion2 { get { return _selectedVersion2; } set { if (value != null && (_selectedVersion2 == null || _selectedVersion2.Guid != value.Guid)) { _selectedVersion2 = value; RaisePropertyChangedAuto(); OnSelectedVersionChanged(); } } } private bool _isShowDifference; /// /// Gets or sets a value indicating whether this instance is show difference. Binding to value of checkbox in GUI. /// /// /// true if this instance is show difference; otherwise, false. /// public bool IsShowDifference { get { return _isShowDifference; } set { _isShowDifference = value; RaisePropertyChangedAuto(); } } private HardwareCompareResult _result; /// /// Gets or sets the result. Contains result of the comparison properties from selected versions. /// /// /// The result. /// public HardwareCompareResult Result { get { return _result; } set { _result = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private bool _isRunning; public bool IsRunning { get { return _isRunning; } set { _isRunning = value; RaisePropertyChangedAuto(); } } #endregion properties #region Command public RelayCommand GenerateReportCommand { get; set; } #endregion #region Constructors public ComparisonWizardViewVM(IEnumerable availableVersions, HardwareVersion selectedVersion, INotificationProvider notification) { HardwareVersions = new ObservableCollection(availableVersions); _selectedVersion1 = selectedVersion; _isShowDifference = false; IsRunning = false; IsShowDifference = true; _notification = notification; GenerateReportCommand = new RelayCommand(GenerateReport, () => Result != null); } #endregion #region Report /// /// Generates the report. Save properties in .csv file in format Collection name/Component name/Property name/Value1 of version1/Value2 of version 2 /// private void GenerateReport() { SaveFileDialog dlg = new SaveFileDialog(); dlg.Title = "Save Report"; dlg.Filter = "CSV Files|*.csv"; dlg.FileName = $"hw_compare_report__{SelectedVersion1.Name}__vs__{SelectedVersion2.Name}"; dlg.DefaultExt = ".csv"; if (dlg.ShowDialog().Value) { try { CsvFile csvFile = new CsvFile(new CsvDestination(dlg.FileName), new CsvDefinition() { Columns = new List() { "Collection", "Component", "Property", SelectedVersion1.Name, SelectedVersion2.Name, }, }); foreach (var collection in Result.Collections.Where(x => x.HasDifferences || !IsShowDifference)) { ReportModel model_collection = new ReportModel(); model_collection.Collection = collection.CollectionName; csvFile.Append(model_collection); foreach (var component in collection.Components.Where(x => x.HasDifferences || !IsShowDifference)) { ReportModel model_component = new ReportModel(); model_component.Component = component.ComponentName; csvFile.Append(model_component); foreach (var prop in component.Properties.Where(x => x.HasDifferences || !IsShowDifference)) { ReportModel model = new ReportModel(); model.Property = prop.PropertyName; model.HW_1 = prop.Value1; model.HW_2 = prop.Value2; csvFile.Append(model); } } } csvFile.Dispose(); _notification.ShowInfo("Report generated successfully."); } catch (Exception ex) { LogManager.Log(ex, "Error generating HW version comparison report."); _notification.ShowError($"Error generating HW version comparison report.\n{ex.Message}"); } } } #endregion #region Selected Version Changed private async void OnSelectedVersionChanged() { if (SelectedVersion1 != null && SelectedVersion2 != null) { IsRunning = true; using (ObservablesContext db = ObservablesContext.CreateDefault()) { var h1 = await new HardwareVersionBuilder(db).Set(SelectedVersion1.Guid).WithHardwareComponents().BuildAsync(); var h2 = await new HardwareVersionBuilder(db).Set(SelectedVersion2.Guid).WithHardwareComponents().BuildAsync(); await Task.Factory.StartNew(() => { Result = CompareHardwareVersions(h1, h2); IsRunning = false; }); } } } #endregion #region Compare Versions private HardwareCompareResult CompareHardwareVersions(HardwareVersion h1, HardwareVersion h2) { _result = new HardwareCompareResult(); _result.Collections.Add(CompareMotorsCollection(h1, h2)); _result.Collections.Add(CompareDancerCollection(h1, h2)); _result.Collections.Add(ComparePidControlsCollection(h1, h2)); _result.Collections.Add(CompareWindersCollection(h1, h2)); _result.Collections.Add(CompareSpeedSensorsCollection(h1, h2)); _result.Collections.Add(CompareBlowersCollection(h1, h2)); _result.Collections.Add(CompareBreakSensorCollection(h1, h2)); return _result; } private HardwareComponentCollectionCompareResult CompareMotorsCollection(HardwareVersion h1, HardwareVersion h2) { HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult() { CollectionName = "MOTORS" }; foreach (var motorTypeCode in Enum.GetValues(typeof(HardwareMotorTypes)).Cast()) { var motor1 = h1.HardwareMotors.SingleOrDefault(x => x.HardwareMotorType.Code == motorTypeCode.ToInt32()); var motor2 = h2.HardwareMotors.SingleOrDefault(x => x.HardwareMotorType.Code == motorTypeCode.ToInt32()); var componentResult = CompareComponents( motorTypeCode.ToDescription(), GetComponentProperties(typeof(HardwareMotorBase)), motor1, motor2); collection.Components.Add(componentResult); } collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection(); return collection; } private HardwareComponentCollectionCompareResult CompareDancerCollection(HardwareVersion h1, HardwareVersion h2) { HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult() { CollectionName = "DANCERS" }; foreach (var dancerTypeCode in Enum.GetValues(typeof(HardwareDancerTypes)).Cast()) { var motor1 = h1.HardwareDancers.SingleOrDefault(x => x.HardwareDancerType.Code == dancerTypeCode.ToInt32()); var motor2 = h2.HardwareDancers.SingleOrDefault(x => x.HardwareDancerType.Code == dancerTypeCode.ToInt32()); var componentResult = CompareComponents( dancerTypeCode.ToDescription(), GetComponentProperties(typeof(HardwareDancerBase)), motor1, motor2); collection.Components.Add(componentResult); } collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection(); return collection; } private HardwareComponentCollectionCompareResult ComparePidControlsCollection(HardwareVersion h1, HardwareVersion h2) { HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult() { CollectionName = "PID CONTROLS" }; foreach (var pidControlsTypeCode in Enum.GetValues(typeof(HardwarePidControlTypes)).Cast()) { var motor1 = h1.HardwarePidControls.SingleOrDefault(x => x.HardwarePidControlType.Code == pidControlsTypeCode.ToInt32()); var motor2 = h2.HardwarePidControls.SingleOrDefault(x => x.HardwarePidControlType.Code == pidControlsTypeCode.ToInt32()); var componentResult = CompareComponents( pidControlsTypeCode.ToDescription(), GetComponentProperties(typeof(HardwarePidControlBase)), motor1, motor2); collection.Components.Add(componentResult); } collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection(); return collection; } private HardwareComponentCollectionCompareResult CompareWindersCollection(HardwareVersion h1, HardwareVersion h2) { HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult() { CollectionName = "WINDERS" }; foreach (var WinderTypeCode in Enum.GetValues(typeof(HardwareWinderTypes)).Cast()) { var motor1 = h1.HardwareWinders.SingleOrDefault(x => x.HardwareWinderType.Code == WinderTypeCode.ToInt32()); var motor2 = h2.HardwareWinders.SingleOrDefault(x => x.HardwareWinderType.Code == WinderTypeCode.ToInt32()); var componentResult = CompareComponents( WinderTypeCode.ToDescription(), GetComponentProperties(typeof(HardwareWinderBase)), motor1, motor2); collection.Components.Add(componentResult); } collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection(); return collection; } private HardwareComponentCollectionCompareResult CompareSpeedSensorsCollection(HardwareVersion h1, HardwareVersion h2) { HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult() { CollectionName = "SPEED SENSORS" }; foreach (var speedSewnsorsTypeCode in Enum.GetValues(typeof(HardwareSpeedSensorTypes)).Cast()) { var motor1 = h1.HardwareSpeedSensors.SingleOrDefault(x => x.HardwareSpeedSensorType.Code == speedSewnsorsTypeCode.ToInt32()); var motor2 = h2.HardwareSpeedSensors.SingleOrDefault(x => x.HardwareSpeedSensorType.Code == speedSewnsorsTypeCode.ToInt32()); var componentResult = CompareComponents( speedSewnsorsTypeCode.ToDescription(), GetComponentProperties(typeof(HardwareSpeedSensorBase)), motor1, motor2); collection.Components.Add(componentResult); } collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection(); return collection; } private HardwareComponentCollectionCompareResult CompareBlowersCollection(HardwareVersion h1, HardwareVersion h2) { HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult() { CollectionName = "BLOWERS" }; foreach (var blowersTypeCode in Enum.GetValues(typeof(HardwareBlowerTypes)).Cast()) { var motor1 = h1.HardwareBlowers.SingleOrDefault(x => x.HardwareBlowerType.Code == blowersTypeCode.ToInt32()); var motor2 = h2.HardwareBlowers.SingleOrDefault(x => x.HardwareBlowerType.Code == blowersTypeCode.ToInt32()); var componentResult = CompareComponents( blowersTypeCode.ToDescription(), GetComponentProperties(typeof(HardwareBlowerBase)), motor1, motor2); collection.Components.Add(componentResult); } collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection(); return collection; } private HardwareComponentCollectionCompareResult CompareBreakSensorCollection(HardwareVersion h1, HardwareVersion h2) { HardwareComponentCollectionCompareResult collection = new HardwareComponentCollectionCompareResult() { CollectionName = "BREAK SENSOR" }; foreach (var breakSewnsorsTypeCode in Enum.GetValues(typeof(HardwareBreakSensorTypes)).Cast()) { var motor1 = h1.HardwareBreakSensors.SingleOrDefault(x => x.HardwareBreakSensorType.Code == breakSewnsorsTypeCode.ToInt32()); var motor2 = h2.HardwareBreakSensors.SingleOrDefault(x => x.HardwareBreakSensorType.Code == breakSewnsorsTypeCode.ToInt32()); var componentResult = CompareComponents( breakSewnsorsTypeCode.ToDescription(), GetComponentProperties(typeof(HardwareBreakSensorBase)), motor1, motor2); collection.Components.Add(componentResult); } collection.Components = collection.Components.OrderByAlphaNumeric(x => x.ComponentName).ToSynchronizedObservableCollection(); return collection; } private HardwareComponentCompareResult CompareComponents(String name, List properties, Object component1, Object component2) { HardwareComponentCompareResult result = new HardwareComponentCompareResult(); result.ComponentName = name; result.HasComponent1 = component1 != null; result.HasComponent2 = component2 != null; foreach (var prop in properties) { var hProp = new HardwareComponentPropertyResult(); hProp.PropertyName = prop.Name; hProp.Value1 = component1 != null ? (prop.GetValue(component1) == null ? "" : prop.GetValue(component1).ToString()) : null; hProp.Value2 = component2 != null ? (prop.GetValue(component2) == null ? "" : prop.GetValue(component2).ToString()) : null; result.Properties.Add(hProp); } return result; } private List GetComponentProperties(Type componentType) { List exclude = new List() { "Guid", "ID", "LastUpdated", "Parameters", }; return componentType.GetProperties(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public).Where(x => !x.PropertyType.IsClass && !exclude.Contains(x.Name)).ToList(); } #endregion } }