Files
DP44/DTS Viewer/DTS.Viewer.Modules/DTS.Viewer.AddCalculatedChannel/ViewModel/AddCalculatedChannelViewModel.cs
2026-04-17 14:55:32 -04:00

1191 lines
46 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using DTS.Common;
using DTS.Common.Base;
using DTS.Common.Classes.Viewer.Commands;
using DTS.Common.DAS.Concepts;
using DTS.Common.Enums.Sensors;
using DTS.Common.Events;
using DTS.Common.Interactivity;
using DTS.Common.Interface;
using DTS.Common.Utilities.Logging;
using DTS.Common.Utils;
using DTS.Slice.Control;
using DTS.Viewer.AddCalculatedChannel.Model;
using Prism.Events;
using Prism.Regions;
using Unity;
using Test = DTS.Serialization.Test;
// ReSharper disable once CheckNamespace
namespace DTS.Viewer.AddCalculatedChannel
{
public class AddCalculatedChannelViewModel : BaseViewModel<IAddCalculatedChannelViewModel>, IAddCalculatedChannelViewModel
{
#region enums
private enum Tags
{
ChannelName,
ChannelDescription,
IsoCode,
SelectedCalculation,
SourceChannel,
ChannelList,
ChannelListObjects,
SingleChannelSelectorVisibility,
MultipleChannelSelectorVisibility,
ThreeDIRTRACCVisibility,
IRTraccChannelList,
IRTraccChannel,
Pot1ChannelList,
Pot1Channel,
Pot2ChannelList,
Pot2Channel
}
public enum Calculation
{
[Description("Integral")]
Integral = 0,
[Description("Double Integral")]
DoubleIntegral = 1,
[Description("Derivative")]
Derivative = 2,
[Description("Sin")]
Sin = 3,
[Description("Cos")]
Cos = 4,
[Description("3D IR-Tracc")]
ThreeDIRTracc = 5,
[Description("SUM")]
SUM = 6,
[Description("Average")]
AVE = 7,
[Description("3D IR-TRACC Abdomen")]
ThreeDIRTraccAbdomen = 8,
[Description("3D IR-TRACC Lower Thorax")]
ThreeDIRTraccLowerThorax = 9,
[Description("Resultant")]
Resultant = 10,
[Description("HIC")]
HIC = 11
}
#endregion
public IBaseView View { get; set; }
public IBaseViewModel Parent { get; set; }
public object ContextSearchRegion { get; set; }
private IEventAggregator _eventAggregator { get; set; }
private IUnityContainer UnityContainer { get; set; }
public InteractionRequest<Notification> NotificationRequest { get; private set; }
public new InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
/// <summary>
/// Creates a new instance of the AddCalculatedChannelViewModel.
/// </summary>
/// <param name="view">The AddCalculatedChannelView interface.</param>
/// <param name="regionManager">The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed.</param>
/// <param name="eventAggregator">The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other.</param>
/// <param name="unityContainer">The unityContainer.</param>
public AddCalculatedChannelViewModel(IAddCalculatedChannelView view, IRegionManager regionManager, IEventAggregator eventAggregator,
IUnityContainer unityContainer)
: base(regionManager, eventAggregator, unityContainer)
{
View = view;
View.DataContext = this;
NotificationRequest = new InteractionRequest<Notification>();
ConfirmationRequest = new InteractionRequest<Confirmation>();
_eventAggregator = eventAggregator;
UnityContainer = unityContainer;
AddCalculatedChannelCommand = new RelayCommand(AddCalculatedChannel);
}
#region Methods
public void PublishChanges()
{
//throw new NotImplementedException();
}
public override void Initialize()
{
Initialize(null);
}
public override void Initialize(object parameter)
{
Parent = (IBaseViewModel)parameter;
Subscribe();
}
/// <summary>
/// Subscribe for events
/// </summary>
private void Subscribe()
{
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
_eventAggregator.GetEvent<TestSummaryChangeNotification>().Subscribe(OnTestSummaryChanged);
}
/// <summary>
/// Private Event handler for RaiseNotification event.
/// </summary>
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
{
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message,
eventArgsWithTitle.MessageDetails, eventArgsWithTitle.Image);
NotificationRequest.Raise(new Notification
{
Content = eventArgsWithoutTitle,
Title = eventArgsWithTitle.Title
});
}
/// <summary>
/// Read all graphs, calculated channels and channels for the selected test
/// and select and display first group or channel
/// </summary>
/// <param name="list"></param>
private void OnTestSummaryChanged(TestSummaryChangeNotificationArg arg)
{
if (Parent != arg?.ParentVM) return;
var list = arg.SummaryList;
var inputChannels = new List<ITestChannel>();
var inputChannelObjects = new List<ChannelHelper>();
if (list?.Count > 0)
{
foreach (var ts in list)
{
if (ts.Channels.Any() && ts.Channels.FirstOrDefault() == null)
{
// LOAD NOW!
Utils.SetChannelInfo(ts.TestMetadata, Path.GetDirectoryName(ts.TestMetadata.TestRun.FilePath), DTS.Serialization.SliceRaw.File.PersistentChannel.GetIsoCode);
ts.Channels = ts.TestMetadata.TestRun.Channels;
ts.Graphs = ts.TestMetadata.TestSetup.TestGraphs;
ts.CalculatedChannels = ts.TestMetadata.TestRun.CalculatedChannels;
}
if (ts.Channels?.Count > 0)
{
foreach (var c in ts.Channels.Where(ch => null != ch))
{
if (inputChannels.TrueForAll(ch => ch.ChannelId != c.ChannelId))
{
inputChannels.Add(c);
}
}
}
}
inputChannels.Sort(new Comparison<ITestChannel>(CompareDisplayOrders));
}
foreach (var channel in inputChannels)
{
inputChannelObjects.Add(new ChannelHelper(channel));
}
ChannelList = new ObservableCollection<ITestChannel>(inputChannels);
ChannelListObjects = new ObservableCollection<ChannelHelper>(inputChannelObjects);
_HICAccelerationX = null;
OnPropertyChanged("HICAccelerationX");
_HICAccelerationY = null;
OnPropertyChanged("HICAccelerationY");
_HICAccelerationZ = null;
OnPropertyChanged("HICAccelerationZ");
_availableHICChannels = new List<ChannelHelper>();
foreach (var clo in ChannelListObjects)
{
var units = clo.MyChannel.Eu.ToLower().Trim();
if (Constants.ACCELERATION_UNITS.Contains(units))
{
_availableHICChannels.Add(clo);
}
}
OnPropertyChanged("AvailableHICChannels");
bool serializedStringIsValid(string str)
{
var lf = new LinearizationFormula();
lf.FromSerializeString(str);
return lf.IsValid();
}
//itracc
IRTraccChannelList = new ObservableCollection<ChannelHelper>(inputChannels.Where(ch =>
ch.ChannelType == typeof(Test.Module.AnalogInputChannel).ToString() &&
serializedStringIsValid(ch.LinearizationFormula) &&
ch.ZeroMethod == ZeroMethodType.None.ToString() &&
ch.ZeroPoint != 0 &&
ch.FactoryExcitationVoltage != 0).Select(ch => new ChannelHelper(ch)).ToList());
//pot1
Pot1ChannelList = new ObservableCollection<ChannelHelper>(inputChannels.Where(ch =>
ch.ChannelType == typeof(Test.Module.AnalogInputChannel).ToString() &&
(ch.Eu.ToLower().Trim() == "deg" || ch.Eu.ToLower().Trim() == "deg-ang") &&
ch.ZeroMethod == ZeroMethodType.None.ToString() &&
ch.FactoryExcitationVoltage != 0).Select(ch => new ChannelHelper(ch)).ToList());
//pot2
Pot2ChannelList = new ObservableCollection<ChannelHelper>(inputChannels.Where(ch =>
ch.ChannelType == typeof(Test.Module.AnalogInputChannel).ToString() &&
(ch.Eu.ToLower().Trim() == "deg" || ch.Eu.ToLower().Trim() == "deg-ang") &&
ch.ZeroMethod == ZeroMethodType.None.ToString() &&
ch.FactoryExcitationVoltage != 0).Select(ch => new ChannelHelper(ch)).ToList());
}
public override void Activated()
{
SourceChannel = ChannelList.Any() ? ChannelList[0] : null;
IsoCode = "NONE";
SelectedCalculation = CalculationList[0];
ChannelName = "New Channel";
_HICAccelerationX = null;
OnPropertyChanged("HICAccelerationX");
_HICAccelerationY = null;
OnPropertyChanged("HICAccelerationY");
_HICAccelerationZ = null;
OnPropertyChanged("HICAccelerationZ");
_HICLength = 16;
OnPropertyChanged("HICLength");
}
public override void Cleanup()
{
}
#endregion
#region command(s)
public ICommand AddCalculatedChannelCommand { get; private set; }
private void AddCalculatedChannel(object obj)
{
var errors = new List<string>();
var warnings = new List<string>();
var valid = Validate(ref errors, ref warnings, false);
if (errors.Any() || warnings.Any())
{
var toDisplay = new List<string>(errors.ToArray());
toDisplay.AddRange(warnings.ToArray());
_eventAggregator.GetEvent<PageErrorEvent>().Publish(new PageErrorArg(toDisplay.ToArray(), null));
}
if (!valid) { return; }
var error = string.Empty;
try
{
if (null == SelectedCalculation)
{
throw new Exception("No Calculation");
}
var inputChannels = new List<Test.Module.Channel>();
var orderedChannels = new List<Test.Module.Channel>();
var testId = string.Empty;
var channelPath = string.Empty;
switch (SelectedCalculation.MyCalculation)
{
case Calculation.AVE:
case Calculation.SUM:
case Calculation.Resultant:
testId = GetTestIdFromBinaryFileName(ChannelListObjects.First(clo => clo.IsIncluded).MyChannel
.BinaryFileName);
channelPath = ChannelListObjects.First(clo => clo.IsIncluded).MyChannel.BinaryFilePath;
break;
case Calculation.HIC:
testId = GetTestIdFromBinaryFileName(HICAccelerationX.MyChannel.BinaryFileName);
channelPath = HICAccelerationX.MyChannel.BinaryFilePath;
break;
case Calculation.ThreeDIRTracc:
case Calculation.ThreeDIRTraccAbdomen:
case Calculation.ThreeDIRTraccLowerThorax:
testId = GetTestIdFromBinaryFileName(IRTraccChannel.MyChannel.BinaryFileName);
channelPath = IRTraccChannel.MyChannel.BinaryFilePath;
break;
default:
testId = GetTestIdFromBinaryFileName(SourceChannel.BinaryFileName);
channelPath = SourceChannel.BinaryFilePath;
break;
}
var dtsFile = Path.Combine(channelPath, $"{testId}.dts");
Serialization.SliceRaw.File.ReadTestSetup(dtsFile, out var test, out var testSetup, false);
new Event().FromDtsSerializationTest(test, null); //assigns emc objects to all test channels
switch (SelectedCalculation.MyCalculation)
{
case Calculation.AVE:
case Calculation.SUM:
case Calculation.Resultant:
inputChannels.AddRange((from ch in ChannelListObjects
where ch.IsIncluded
select GetTestModuleChannelFromChannelId(test.Modules, ch.MyChannel.ChannelId)).ToList());
break;
case Calculation.HIC:
inputChannels.Add(GetTestModuleChannelFromChannelId(test.Modules, HICAccelerationX.MyChannel.ChannelId));
inputChannels.Add(GetTestModuleChannelFromChannelId(test.Modules, HICAccelerationY.MyChannel.ChannelId));
inputChannels.Add(GetTestModuleChannelFromChannelId(test.Modules, HICAccelerationZ.MyChannel.ChannelId));
break;
case Calculation.ThreeDIRTracc:
case Calculation.ThreeDIRTraccAbdomen:
case Calculation.ThreeDIRTraccLowerThorax:
inputChannels.AddRange(new[]
{
GetTestModuleChannelFromChannelId(test.Modules, IRTraccChannel.MyChannel.ChannelId),
GetTestModuleChannelFromChannelId(test.Modules, Pot1Channel.MyChannel.ChannelId),
GetTestModuleChannelFromChannelId(test.Modules, Pot2Channel.MyChannel.ChannelId)
});
break;
default:
inputChannels.Add(GetTestModuleChannelFromChannelId(test.Modules, SourceChannel.ChannelId));
break;
}
foreach (var m in test.Modules)
{
orderedChannels.AddRange(m.Channels);
orderedChannels.AddRange(m.CalculatedChannels);
}
orderedChannels.Sort(new Comparison<Test.Module.Channel>(CompareDisplayOrders));
var maxDisplayOrder = 0;
try
{
maxDisplayOrder =
(from ch in orderedChannels select ch.AbsoluteDisplayOrder)
.Max();
}
catch (Exception ex)
{
APILogger.Log(ex);
}
var ccs = CalculatedChannelCreator.CreateChannels(testId, channelPath,
SelectedCalculation.MyCalculation, inputChannels, ChannelName, maxDisplayOrder + 1,
orderedChannels, HICLength, out var errorList, DefaultDTSEncoding);
if (ccs == null)
{
if (errorList?.Count > 0)
{
throw new Exception(string.Join(Environment.NewLine, errorList));
}
else
{
throw new Exception("Could not create Calculated Channel(s)");
}
}
foreach (var cc in ccs)
{
if (null != cc)
{
//Channel is created. Hook up to Test structure.
if (AddCalculatedChannelToTest(cc))
{
//Save Test
try
{
//Back up dts file only if a backup file does not exist. This should guarantee that the
//original file is the only one that is preserved.
var dtsFilePath = Path.Combine(channelPath, testId + ".dts");
var dtsBackupFilePath = dtsFilePath + DTS.Common.Constants.BACKUP_FILE_EXTENSION;
var backupExisted = System.IO.File.Exists(dtsBackupFilePath);
if (!backupExisted && System.IO.File.Exists(dtsFilePath))
{
System.IO.File.Move(dtsFilePath, dtsBackupFilePath);
}
//Spit out <Test> portion
var f =
new Serialization.SliceRaw.File { DefaultEncoding = DefaultDTSEncoding };
//Write the SLICEWare-compatible info so that SLICEWare can display the data if desired.
//UTF-16
f.Exporter.Write(channelPath, testId, test, false,
IncludeGroupNameInISOExport, Common.Constants.UNUSED_START_TIME,
Common.Constants.UNUSED_DATA_COLLECTION_LENGTH);
//Append the <TestSetup> DataPRO info to the end of the existing .dts file which already contains SLICEWare-compatible info
using (var writer = new StringWriter())
{
new System.Xml.Serialization.XmlSerializer(typeof(DTS.Serialization.TestSetup))
.Serialize(writer,
testSetup);
Encoding encoder;
try
{
encoder = Encoding.GetEncoding(DefaultDTSEncoding);
}
catch (Exception ex)
{
APILogger.Log("Problem getting encoder", ex);
encoder = Encoding.Default;
}
using (var fileWriter = new StreamWriter(dtsFilePath, true, encoder))
{
fileWriter.Write(fileWriter.NewLine + writer);
//FB9374: successful save without error. if we created a backup for this save, remove it
if (!backupExisted) System.IO.File.Delete(dtsBackupFilePath);
}
System.Threading.Thread.Sleep(10);
}
_eventAggregator?.GetEvent<RefreshTestRequestEvent>().Publish(dtsFilePath);
}
catch (Exception)
{
error = "Error creating Test with Calculated Channel";
}
}
}
}
}
catch (Exception ex)
{
error = ex.Message;
}
finally
{
//(App.Current as App).SetAppAvailable();
}
if (!string.IsNullOrEmpty(error))
{
_eventAggregator.GetEvent<RaiseNotification>().Publish(new NotificationContentEventArgs(error));
}
}
private bool AddCalculatedChannelToTest(Test.Module.CalculatedChannel cchannel)
{
try
{
//Remove any duplicates in the list
foreach (var c in cchannel.ParentModule.CalculatedChannels)
{
if (cchannel.ChannelId.Equals(c.ChannelId))
{
APILogger.Log("Overwriting existing calculated channel " + c);
cchannel.ParentModule.CalculatedChannels.Remove(c);
break;
}
}
//Calculated Channels are stored in module. Save test to commit.
cchannel.ParentModule.CalculatedChannels.Add(cchannel);
return true;
}
catch (Exception ex)
{
APILogger.LogException(ex);
}
return false;
}
#endregion
#region ContextRegion
#endregion
#region Properties
///<summary>
///Occurs when a property value changes.
///</summary>
public new event PropertyChangedEventHandler PropertyChanged;
private new void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
/// <summary>
/// Gets the HeaderInfo.
/// </summary>
public string HeaderInfo => "AddCalculatedChannelRegion";
public new bool IsBusy
{
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
public new bool IsDirty => throw new NotImplementedException();
public bool IsAddCalculatedChannelIncluded { get; set; }
public bool IncludeGroupNameInISOExport { get; set; }
public int DefaultDTSEncoding { get; set; }
private string _channelName = string.Empty;
public string ChannelName
{
get => _channelName;
set
{
_channelName = value;
OnPropertyChanged(Tags.ChannelName.ToString());
UpdateSaveButtonVisibility();
}
}
private string _channelDescription = string.Empty;
public string ChannelDescription
{
get => _channelDescription;
set
{
_channelDescription = value;
OnPropertyChanged(Tags.ChannelDescription.ToString());
}
}
private string _isoCode = string.Empty;
public string IsoCode
{
get => _isoCode;
set
{
_isoCode = value;
OnPropertyChanged(Tags.IsoCode.ToString());
UpdateSaveButtonVisibility();
}
}
private bool _singleChannelSelectorVisibility = false;
public bool SingleChannelSelectorVisibility
{
get => _singleChannelSelectorVisibility;
set
{
_singleChannelSelectorVisibility = value;
OnPropertyChanged(Tags.SingleChannelSelectorVisibility.ToString());
}
}
private bool _hicChannelSelectorVisibility = false;
/// <summary>
/// whether HIC is visible or not
/// </summary>
public bool HICChannelSelectorVisibility
{
get => _hicChannelSelectorVisibility;
set
{
_hicChannelSelectorVisibility = value;
OnPropertyChanged("HICChannelSelectorVisibility");
}
}
private bool _multipleChannelSelectorVisibility = true;
public bool MultipleChannelSelectorVisibility
{
get => _multipleChannelSelectorVisibility;
set
{
_multipleChannelSelectorVisibility = value;
OnPropertyChanged(Tags.MultipleChannelSelectorVisibility.ToString());
}
}
private bool _threeDIRTRACCVisibility = false;
public bool ThreeDIRTRACCVisibility
{
get => _threeDIRTRACCVisibility;
set
{
_threeDIRTRACCVisibility = value;
OnPropertyChanged(Tags.ThreeDIRTRACCVisibility.ToString());
}
}
private CalculationHelper[] _calculations = null;
public CalculationHelper[] CalculationList
{
get
{
if (null != _calculations) return _calculations;
var enums = Enum.GetValues(typeof(Calculation)).Cast<Calculation>().ToArray();
_calculations = enums.Select(e => new CalculationHelper(e)).ToArray();
SelectedCalculation = _calculations[0];
return _calculations;
}
}
private CalculationHelper _selectedCalculation;
public CalculationHelper SelectedCalculation
{
get => _selectedCalculation;
set
{
_selectedCalculation = value;
OnPropertyChanged(Tags.SelectedCalculation.ToString());
switch (SelectedCalculation.MyCalculation)
{
case Calculation.Integral:
case Calculation.DoubleIntegral:
case Calculation.Derivative:
case Calculation.Sin:
case Calculation.Cos:
SingleChannelSelectorVisibility = true;
MultipleChannelSelectorVisibility = false;
HICChannelSelectorVisibility = false;
ThreeDIRTRACCVisibility = false;
break;
case Calculation.ThreeDIRTracc:
case Calculation.ThreeDIRTraccAbdomen:
case Calculation.ThreeDIRTraccLowerThorax:
SingleChannelSelectorVisibility = false;
MultipleChannelSelectorVisibility = false;
HICChannelSelectorVisibility = false;
ThreeDIRTRACCVisibility = true;
break;
case Calculation.SUM:
case Calculation.AVE:
case Calculation.Resultant:
SingleChannelSelectorVisibility = false;
MultipleChannelSelectorVisibility = true;
HICChannelSelectorVisibility = false;
ThreeDIRTRACCVisibility = false;
break;
case Calculation.HIC:
SingleChannelSelectorVisibility = false;
MultipleChannelSelectorVisibility = false;
HICChannelSelectorVisibility = true;
ThreeDIRTRACCVisibility = false;
break;
}
if (ThreeDIRTRACCVisibility)
{
IRTraccChannel = IRTraccChannelList.Any() ? IRTraccChannelList[0] : null;
Pot1Channel = Pot1ChannelList.Any() ? Pot1ChannelList[0] : null;
Pot2Channel = Pot2ChannelList.Any() ? Pot2ChannelList[0] : null;
}
UpdateChannelDescription();
UpdateSaveButtonVisibility();
}
}
private void UpdateChannelDescription()
{
if (null != SelectedCalculation)
{
switch (SelectedCalculation.MyCalculation)
{
case Calculation.ThreeDIRTracc:
case Calculation.ThreeDIRTraccAbdomen:
case Calculation.ThreeDIRTraccLowerThorax:
ChannelDescription = null != IRTraccChannel ? IRTraccChannel.ChannelName + " : " + SelectedCalculation.ToString().ToUpper() : "";
break;
case Calculation.SUM:
case Calculation.AVE:
ChannelDescription = "";
if (ChannelListObjects.Any(clo => clo.IsIncluded))
{
foreach (var clo in ChannelListObjects.Where(clo => clo.IsIncluded))
{
if (!string.IsNullOrEmpty(ChannelDescription))
ChannelDescription += ", ";
ChannelDescription += clo.MyChannel.ChannelDescriptionString;
}
ChannelDescription += " : " + SelectedCalculation.ToString().ToUpper();
}
break;
default:
ChannelDescription = null != _sourceChannel ? _sourceChannel + " : " + SelectedCalculation.ToString().ToUpper() : "";
break;
}
}
else
{
ChannelDescription = "";
}
}
private void UpdateSaveButtonVisibility()
{
if ((null != SelectedCalculation) &&
(false == string.IsNullOrEmpty(ChannelDescription)))
{
switch (SelectedCalculation.MyCalculation)
{
case Calculation.ThreeDIRTracc:
case Calculation.ThreeDIRTraccAbdomen:
case Calculation.ThreeDIRTraccLowerThorax:
if (null == IRTraccChannel || null == Pot1Channel || null == Pot2Channel) { _eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = false }); }
else { _eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = true }); }
break;
case Calculation.SUM:
case Calculation.AVE:
if (ChannelListObjects.All(clo => !clo.IsIncluded)) { _eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = false }); }
else { _eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = true }); }
break;
case Calculation.HIC:
if (null == HICAccelerationX || null == HICAccelerationY || null == HICAccelerationZ)
{
_eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = true });
}
else
{
_eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = false });
}
break;
default:
if ((null != SourceChannel) && (false == string.IsNullOrEmpty(ChannelName)) && (false == string.IsNullOrEmpty(IsoCode)))
{ _eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = true }); }
break;
}
}
else
{
_eventAggregator.GetEvent<SetSaveButton>().Publish(new SaveButtonUsability() { IsUsable = false });
}
}
private ObservableCollection<ITestChannel> _channelList = new ObservableCollection<ITestChannel>();
public ObservableCollection<ITestChannel> ChannelList
{
get => _channelList;
set
{
_channelList = value;
OnPropertyChanged(Tags.ChannelList.ToString());
}
}
private List<ChannelHelper> _availableHICChannels = new List<ChannelHelper>();
/// <summary>
/// all HIC possible channels (g,m/sec,m/sec^2 channels)
/// </summary>
public ChannelHelper[] AvailableHICChannels
{
get => _availableHICChannels.ToArray();
set
{
_availableHICChannels.Clear();
_availableHICChannels.AddRange(value);
OnPropertyChanged("AvailableHICChannels");
}
}
private ChannelHelper _HICAccelerationX;
/// <summary>
/// currently selected head acceleration x
/// </summary>
public ChannelHelper HICAccelerationX
{
get => _HICAccelerationX;
set
{
_HICAccelerationX = value;
OnPropertyChanged("HICAccelerationX");
}
}
private ChannelHelper _HICAccelerationY;
/// <summary>
/// currently selected head acceleration y
/// </summary>
public ChannelHelper HICAccelerationY
{
get => _HICAccelerationY;
set
{
_HICAccelerationY = value;
OnPropertyChanged("HICAccelerationY");
}
}
private ChannelHelper _HICAccelerationZ;
/// <summary>
/// currently selected head acceleration z
/// </summary>
public ChannelHelper HICAccelerationZ
{
get => _HICAccelerationZ;
set
{
_HICAccelerationZ = value;
OnPropertyChanged("HICAccelerationZ");
}
}
private ITestChannel _sourceChannel;
public ITestChannel SourceChannel
{
get => _sourceChannel;
set
{
_sourceChannel = value;
OnPropertyChanged(Tags.SourceChannel.ToString());
UpdateChannelDescription();
UpdateSaveButtonVisibility();
}
}
private ObservableCollection<ChannelHelper> _channelListObjects = new ObservableCollection<ChannelHelper>();
public ObservableCollection<ChannelHelper> ChannelListObjects
{
get => _channelListObjects;
set
{
foreach (var clo in _channelListObjects)
{
clo.PropertyChanged -= OnChannelListObjectPropertyChanged;
}
_channelListObjects = value;
foreach (var clo in _channelListObjects)
{
clo.PropertyChanged += OnChannelListObjectPropertyChanged;
}
OnPropertyChanged(Tags.ChannelListObjects.ToString());
}
}
private void OnChannelListObjectPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
UpdateChannelDescription();
UpdateSaveButtonVisibility();
}
private ObservableCollection<ChannelHelper> _irTraccChannelList = new ObservableCollection<ChannelHelper>();
public ObservableCollection<ChannelHelper> IRTraccChannelList
{
get => _irTraccChannelList;
set
{
_irTraccChannelList = value;
OnPropertyChanged(Tags.IRTraccChannelList.ToString());
}
}
private ChannelHelper _irTraccChannel;
public ChannelHelper IRTraccChannel
{
get => _irTraccChannel;
set
{
_irTraccChannel = value;
OnPropertyChanged(Tags.IRTraccChannel.ToString());
UpdateSaveButtonVisibility();
}
}
private ObservableCollection<ChannelHelper> _pot1ChannelList = new ObservableCollection<ChannelHelper>();
public ObservableCollection<ChannelHelper> Pot1ChannelList
{
get => _pot1ChannelList;
set
{
_pot1ChannelList = value;
OnPropertyChanged(Tags.Pot1ChannelList.ToString());
}
}
private int _HICLength = 16;
public int HICLength
{
get => _HICLength;
set
{
_HICLength = value;
OnPropertyChanged("HICLength");
}
}
private ChannelHelper _pot1Channel;
public ChannelHelper Pot1Channel
{
get => _pot1Channel;
set
{
_pot1Channel = value;
OnPropertyChanged(Tags.Pot1Channel.ToString());
UpdateSaveButtonVisibility();
}
}
private ObservableCollection<ChannelHelper> _pot2ChannelList = new ObservableCollection<ChannelHelper>();
public ObservableCollection<ChannelHelper> Pot2ChannelList
{
get => _pot2ChannelList;
set
{
_pot2ChannelList = value;
OnPropertyChanged(Tags.Pot2ChannelList.ToString());
}
}
private ChannelHelper _pot2Channel;
public ChannelHelper Pot2Channel
{
get => _pot2Channel;
set
{
_pot2Channel = value;
OnPropertyChanged(Tags.Pot2Channel.ToString());
UpdateSaveButtonVisibility();
}
}
#endregion
#region validate
public bool Validate(ref List<string> errors, ref List<string> warnings, bool displayWindow)
{
var res = ValidateChannelName();
switch (SelectedCalculation.MyCalculation)
{
case Calculation.HIC:
if (!ValidateHIC(ref errors, ref warnings))
{
res = false;
}
break;
case Calculation.Resultant:
if (!ValidateResultant(ref errors, ref warnings))
{
res = false;
}
break;
}
return res;
}
private bool ValidateHIC(ref List<string> errors, ref List<string> warnings)
{
//validate 3 channels
if (null == HICAccelerationX || null == HICAccelerationY || null == HICAccelerationZ)
{
errors.Add(Resources.StringResources.HICRequires3Channels);
return false;
}
return true;
}
private bool ValidateResultant(ref List<string> errors, ref List<string> warnings)
{
//validate same units across channel
var included = from clo in ChannelListObjects where clo.IsIncluded select clo;
if (!included.Any())
{
errors.Add(Resources.StringResources.NoChannelsIncluded);
return false;
}
string units = null;
int sps = -1;
foreach (var clo in included)
{
if (null == units)
{
units = clo.MyChannel.SensitivityUnits;
sps = clo.MyChannel.SampleRateHz;
}
else
{
if (units != clo.MyChannel.SensitivityUnits)
{
errors.Add(Resources.StringResources.ResultantUnitsDontMatch);
return false;
}
if (sps != clo.MyChannel.SampleRateHz)
{
errors.Add(Resources.StringResources.SampleRatesDontMatch);
return false;
}
}
}
return true;
}
public bool ValidateChannelName()
{
if (!string.IsNullOrEmpty(ChannelName)) return true;
return false;
}
#endregion
#region helpers
private static Test.Module.Channel GetTestModuleChannelFromChannelId(List<Test.Module> modules, string channelID)
{
foreach (var m in modules.Where(x => x.Channels.Exists(ch => ch.ChannelId == channelID)))
{
return m.Channels.Find(ch => ch.ChannelId == channelID);
}
return null;
}
/// <summary>
/// returns the test id from a binary filename
/// it didn't seem the test id was available from any of the structures I had access to
/// but it's the portion of the file name without all the decoration
/// the filename is in the form of TestIdChxxx.yyy.chn
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
private static string GetTestIdFromBinaryFileName(string filename)
{
var index = filename.IndexOf('.');
filename = filename.Substring(0, index);
index = filename.LastIndexOf("Ch", StringComparison.Ordinal);
//we expect the Ch, but if we don't find it, use the what portion we have
return index >= 0 ? filename.Substring(0, index) : filename;
}
private static int CompareDisplayOrders(ITestChannel a, ITestChannel b)
{
if (a == b)
{
return 0;
}
if (null == a)
{
return -1;
}
if (null == b)
{
return 1;
}
return a.AbsoluteDisplayOrder.CompareTo(b.AbsoluteDisplayOrder);
}
private static int CompareDisplayOrders(Test.Module.Channel a, Test.Module.Channel b)
{
if (a == b)
{
return 0;
}
if (null == a)
{
return -1;
}
if (null == b)
{
return 1;
}
return a.AbsoluteDisplayOrder.CompareTo(b.AbsoluteDisplayOrder);
}
#endregion
#region helper classes
public class ChannelHelper : BasePropertyChanged
{
public ITestChannel MyChannel
{
get;
private set;
}
public ChannelHelper(ITestChannel c)
{
MyChannel = c;
var channelName = string.Empty;
var code = string.Empty;
switch (Common.Enums.IsoViewModeStatic.ViewMode)
{
case Common.Enums.IsoViewMode.ISOOnly:
channelName = c.IsoChannelName;
code = c.IsoCode;
break;
case Common.Enums.IsoViewMode.ISOAndUserCode:
channelName = $"{c.IsoChannelName}/{c.UserChannelName}";
code = $"{c.IsoCode}/{c.UserCode}";
break;
case Common.Enums.IsoViewMode.UserCodeOnly:
channelName = c.UserChannelName;
code = $"{c.UserCode}";
break;
case Common.Enums.IsoViewMode.ChannelNameOnly:
channelName = c.UserChannelName;
code = string.Empty;
break;
}
DisplayName = $"{channelName}/{code}/[{c.ToString()}]";
}
public override string ToString()
{
return MyChannel.ChannelDescriptionString;
}
private string _displayName;
public string DisplayName
{
get => _displayName;
set
{
_displayName = value;
OnPropertyChanged("DisplayName");
}
}
public string ChannelName => ToString();
private bool _bIncluded = false;
public bool IsIncluded
{
get => _bIncluded;
set => SetProperty(ref _bIncluded, value, "IsIncluded");
}
}
public class CalculationHelper
{
public Calculation MyCalculation { get; private set; }
public CalculationHelper(Calculation calc) { MyCalculation = calc; }
public override string ToString()
{
return Resources.StringResources.ResourceManager.GetString("CALCULATION_" + MyCalculation) ?? MyCalculation.ToString();
}
}
#endregion
}
}