init
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
using DTS.Common.Base;
|
||||
using DTS.Common.Interface;
|
||||
using Microsoft.Practices.Prism.Events;
|
||||
|
||||
namespace DTS.Common.Events
|
||||
{
|
||||
public class PSDReportGRMSValuesUpdatedEvent : CompositePresentationEvent<PSDReportGRMSValuesUpdatedEventArg> { }
|
||||
|
||||
public class PSDReportGRMSValuesUpdatedEventArg
|
||||
{
|
||||
public IChannelGRMSSummary[] Values { get; set; }
|
||||
public IBaseViewModel ParentVM { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using DTS.Common.Base;
|
||||
|
||||
namespace DTS.Common.Interface
|
||||
{
|
||||
public interface ICursorViewModel : IBaseViewModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Tab View.
|
||||
/// </summary>
|
||||
ICursorView View { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<UserControl x:Class="DTS.Common.Controls.GridViewColumnHeaderSearchableCheckBox"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:DTS.Common.Controls"
|
||||
xmlns:strings="clr-namespace:DTS.Common.Strings"
|
||||
mc:Ignorable="d"
|
||||
x:Name="dtsGridViewColumnHeader"
|
||||
d:DesignHeight="20" d:DesignWidth="200">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<Geometry x:Key="DownArrowIconGeometry">F0 M 0,0L 10,0L 5,7L 0,0 Z</Geometry>
|
||||
<local:BoolToInvertedBoolConverter x:Key="BoolToInvertedBoolConverter"/>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource PageContentButtonDark}" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</UserControl.Resources>
|
||||
<Grid DataContext="{Binding ElementName=dtsGridViewColumnHeader}" x:Name="mainGrid" Height="20" MaxHeight="20">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border BorderThickness="0" Grid.Column="0" PreviewMouseLeftButtonDown="PreviewLeftButtonUp">
|
||||
<TextBlock Text="{Binding Path=HeaderTitle, FallbackValue='I Should Not Be Here'}" HorizontalAlignment="Left" Margin="5,0,5,0" />
|
||||
</Border>
|
||||
<!--<Button Grid.Column="0" Content="{Binding Path=HeaderTitle, FallbackValue='I should not be here'}" HorizontalAlignment="Left" Margin="5,0,5,0" Click="ButtonClick" /> -->
|
||||
<ToggleButton Grid.Column="1" x:Name="TogglePopupButton" Width="20" Height="20" MaxWidth="20" MaxHeight="20" IsEnabled="{Binding ElementName=ToggledPopup, Path=IsOpen, Converter={StaticResource BoolToInvertedBoolConverter}}"
|
||||
IsChecked="{Binding ToggleButtonIsChecked, Mode=TwoWay, FallbackValue=True}">
|
||||
<Path x:Name="BtnArrow" VerticalAlignment="Center" HorizontalAlignment="Center" Width="8" Fill="#FF527DB5" Stretch="Uniform"
|
||||
Data="{Binding ToggleIconGeometry, FallbackValue={StaticResource DownArrowIconGeometry}}"/>
|
||||
</ToggleButton>
|
||||
<Popup Grid.Column="0" Grid.ColumnSpan="2" x:Name="ToggledPopup" HorizontalAlignment="Stretch" Placement="Bottom" VerticalAlignment="Stretch" StaysOpen="False" IsOpen="{Binding ToggleButtonIsChecked, Mode=TwoWay}" >
|
||||
<Border Background="#FFEEEEEE" BorderBrush="#FF888888" BorderThickness="1">
|
||||
<StackPanel Orientation="Vertical" VerticalAlignment="Stretch">
|
||||
<Button Padding="10 5" Content="{x:Static strings:Strings.SelectAllParen}" Click="SelectAllButton_OnClick" />
|
||||
<Button Padding="10, 5" Content="{x:Static strings:Strings.True}" Click="TrueButton_OnClick" />
|
||||
<Button Padding="10, 5" Content="{x:Static strings:Strings.False}" Click="FalseButton_OnClick" />
|
||||
</StackPanel>
|
||||
<!--<<Grid HorizontalAlignment="Stretch" Margin="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
Button Grid.Column="0" Padding="10 5" Content="{x:Static strings:Strings.SelectAll}" Click="SelectAllButton_OnClick" />
|
||||
<Button Grid.Column="1" Padding="10 5" Content="{x:Static strings:Strings.ClearAll}" Click="ClearAllButton_OnClick"/>
|
||||
|
||||
</Grid>-->
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
<!--</GridViewColumnHeader>-->
|
||||
</UserControl>
|
||||
@@ -0,0 +1,980 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Xml;
|
||||
using DTS.Common.Enums;
|
||||
using DTS.Common.Enums.Hardware;
|
||||
using DTS.Common.Interface;
|
||||
using DTS.Common.Interface.TestDefinition;
|
||||
using Microsoft.Practices.ObjectBuilder2;
|
||||
|
||||
namespace DTS.Common.Utils
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
private const string LINEAR_PATTERN = ".lin.";
|
||||
|
||||
|
||||
public delegate string GetIsoCodeDelegate(string binaryFileName);
|
||||
/// <summary>
|
||||
/// populates Test.Channels properties with details
|
||||
/// </summary>
|
||||
/// <param name="tmd">Test Metadata list</param>
|
||||
/// <param name="path">file location</param>
|
||||
/// <param name="GetIsoCode">function that returns an isocode given a filepath</param>
|
||||
public static void SetChannelInfo(ITestMetadata tmd, string path, GetIsoCodeDelegate GetIsoCode)
|
||||
{
|
||||
var fileList = new List<string>();
|
||||
|
||||
if (path.Contains("ALL") || path.Contains("ROI"))
|
||||
{
|
||||
fileList = FileUtils.FindFilesInDirectory(path, "chn");
|
||||
}
|
||||
else
|
||||
{
|
||||
FileUtils.FileList = new List<string>();
|
||||
FileUtils.FindFiles(path, "chn");
|
||||
fileList = FileUtils.FileList;
|
||||
}
|
||||
|
||||
var testId = tmd.TestRun.Id;
|
||||
tmd.TestRun.Channels = new List<ITestChannel>();
|
||||
tmd.TestRun.CalculatedChannels = new List<ITestChannel>();
|
||||
var channelCount = 0;
|
||||
foreach (var m in tmd.TestRun.Modules)
|
||||
{
|
||||
var sn = m.SerialNumber;
|
||||
foreach (var ch in m.Channels)
|
||||
{
|
||||
//ch.ChannelNumber = channelCount;
|
||||
ch.ModuleSerialNumber = sn;
|
||||
|
||||
var fullFileName = String.Empty;
|
||||
|
||||
var newStyle = fileList.Where(l => l.Contains(tmd.TestRun.DataType)).Any(f => f.Contains(testId + "Ch"));
|
||||
if (!newStyle)
|
||||
{
|
||||
|
||||
// DataPRO
|
||||
if (!string.IsNullOrEmpty(tmd.TestRun.Software))
|
||||
{
|
||||
var testFileList = fileList
|
||||
.Where(l => l.Contains(tmd.TestRun.DataType) && l.Contains(testId)).ToList();
|
||||
if (channelCount < testFileList.Count)
|
||||
{
|
||||
fullFileName = testFileList[channelCount];
|
||||
}
|
||||
}
|
||||
// SLICEWare
|
||||
else
|
||||
{
|
||||
var testFileList = fileList
|
||||
.Where(l => l.Contains(testId)).ToList();
|
||||
if (channelCount < testFileList.Count)
|
||||
{
|
||||
fullFileName = testFileList[channelCount];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#region new style
|
||||
|
||||
if (ch.Bridge == "SQUIB")
|
||||
{
|
||||
fullFileName = ch.Number % 2 == 0
|
||||
? fileList.Where(l => l.Contains(tmd.TestRun.DataType)).FirstOrDefault(f => f.Contains(testId + "Ch" + (ch.AbsoluteDisplayOrder + 1).ToString("000")))
|
||||
: fileList.Where(l => l.Contains(tmd.TestRun.DataType)).Where(f => f.Contains(testId + "Ch" + (ch.AbsoluteDisplayOrder + 1).ToString("000"))).ToList()[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
var matches = fileList.Where(l => l.Contains(tmd.TestRun.DataType)).Where(f => f.Contains(testId + "Ch" + (ch.AbsoluteDisplayOrder + 1).ToString("000")));
|
||||
//14581 Data for linear, cubic poly sensor differs in run test and view data tile
|
||||
//if we end up with 2 matches, one is the linear added version and one is the non linear version
|
||||
//determine which file we actually want, and use it.
|
||||
if (2 <= matches.Count())
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(ch.LinearizationFormula))
|
||||
{
|
||||
fullFileName = matches.Where(f => f.Contains(LINEAR_PATTERN)).FirstOrDefault();
|
||||
if (null == fullFileName)
|
||||
{
|
||||
//if there are two files and neither contains a .lin, then we've like hit a situation described in
|
||||
//MS 26913 where there was multiple downloads which resulted in the same channel information in two files
|
||||
//we can likely select either of the files in this case as they are probably identical
|
||||
fullFileName = matches.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullFileName = matches.Where(f => !f.Contains(LINEAR_PATTERN)).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullFileName = matches.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion new style
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(fullFileName)) { ch.ErrorMessage = "File does not exist"; }
|
||||
else
|
||||
{
|
||||
ch.BinaryFilePath = Path.GetDirectoryName(fullFileName);
|
||||
ch.BinaryFileName = Path.GetFileName(fullFileName);
|
||||
if (string.IsNullOrEmpty(ch.IsoCode))
|
||||
{
|
||||
ch.IsoCode = GetIsoCode(ch.BinaryFilePath + $"\\" + ch.BinaryFileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ch.ParentModule = m;
|
||||
ch.ParentTestSetup = tmd.TestSetup;
|
||||
tmd.TestRun.Channels.Add(ch);
|
||||
channelCount++;
|
||||
}
|
||||
foreach (var ch in m.CalculatedChannels)
|
||||
{
|
||||
var fullFileName = fileList.Where(l => l.Contains(tmd.TestRun.DataType)).FirstOrDefault(f => f.Contains(testId + "." + ch.Number.ToString()));
|
||||
if (string.IsNullOrEmpty(fullFileName)) { ch.ErrorMessage = "File does not exist"; }
|
||||
else
|
||||
{
|
||||
ch.ModuleSerialNumber = sn;
|
||||
ch.ParentModule = m;
|
||||
ch.ParentTestSetup = tmd.TestSetup;
|
||||
ch.BinaryFilePath = Path.GetDirectoryName(fullFileName);
|
||||
ch.BinaryFileName = Path.GetFileName(fullFileName);
|
||||
}
|
||||
tmd.TestRun.CalculatedChannels.Add(ch);
|
||||
}
|
||||
}
|
||||
foreach (var g in tmd.TestSetup.TestGraphs)
|
||||
{
|
||||
g.Channels = new List<ITestChannel>();
|
||||
foreach (var chId in g.ChannelIds)
|
||||
{
|
||||
var ch = (from c in tmd.TestRun.Channels where c.ChannelId == chId select c).FirstOrDefault();
|
||||
if (ch != null) g.Channels.Add(ch.Copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copied from DataPro
|
||||
/// per http://fogbugz/fogbugz/default.asp?8281 use 120%
|
||||
/// The idea here is to have a moving window no smaller than +/-1% of capacity
|
||||
/// Also make sure that the top of the signal is seen so make the visible window
|
||||
/// +/-120% of the signal
|
||||
/// this was abstrated here from two different locations for:
|
||||
/// 29416 Limit view of TSR AIR data to 1% of full scale in auto range mode
|
||||
/// </summary>
|
||||
/// <param name="capacity">plot expected maximum EU</param>
|
||||
/// <param name="dataMin">actual plot min value</param>
|
||||
/// <param name="dataMax">actual plot max value</param>
|
||||
/// <param name="maxAutoZoom">the scaler to apply to signal as the window max edge</param>
|
||||
/// <param name="minAutoZoom">the scaler to apply to expected maximum to form window min edges</param>
|
||||
/// <param name="currentYMin">min Y value to apply as plot constraint</param>
|
||||
/// <param name="currentYMax">max Y value to apply as plot constraint</param>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
public static void CalculateMinMaxAutoScaling(double capacity,
|
||||
double dataMin,
|
||||
double dataMax,
|
||||
double minAutoZoom,
|
||||
double maxAutoZoom,
|
||||
out double currentYMax,
|
||||
out double currentYMin
|
||||
)
|
||||
{
|
||||
capacity = Math.Abs(capacity);
|
||||
|
||||
var middleOfSignalExtrema = ((dataMax - dataMin) / 2.0D) + dataMin;
|
||||
var minZoom = capacity * minAutoZoom;
|
||||
var topOfMinZoomWindow = middleOfSignalExtrema + minZoom;
|
||||
var bottomOfMinZoomWindow = middleOfSignalExtrema - minZoom;
|
||||
|
||||
currentYMax = (dataMax + Math.Abs(dataMax * (1 - maxAutoZoom)) >= topOfMinZoomWindow) ?
|
||||
dataMax + Math.Abs(dataMax * (1 - maxAutoZoom)) : topOfMinZoomWindow;
|
||||
currentYMin = (dataMin - Math.Abs(dataMin * (1 - maxAutoZoom)) <= bottomOfMinZoomWindow) ?
|
||||
dataMin - Math.Abs(dataMin * (1 - maxAutoZoom)) : bottomOfMinZoomWindow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// test code courtesy of AutoLab XML import/conversion code via Chad Ivan
|
||||
/// the CRC should be prepended to the ID (CRC + ID)
|
||||
/// </summary>
|
||||
/// <param name="ShortID">short ID</param>
|
||||
/// <returns>returns CRC bit for given string</returns>
|
||||
public static string GenerateEIDCRC(string ShortID)
|
||||
{
|
||||
var int64 = Int64.Parse(ShortID, System.Globalization.NumberStyles.HexNumber);
|
||||
var bytes = BitConverter.GetBytes(int64);
|
||||
var bitArray = new System.Collections.BitArray(bytes);
|
||||
var CRCbit = new System.Collections.BitArray(8);
|
||||
var CRCTemp = new System.Collections.BitArray(1);
|
||||
byte[] CRCbyte = new byte[1];
|
||||
|
||||
for (int i = 0; i < 56; i++)
|
||||
{
|
||||
CRCTemp[0] = CRCbit[0] ^ bitArray[i];
|
||||
CRCbit[0] = CRCbit[1];
|
||||
CRCbit[1] = CRCbit[2];
|
||||
CRCbit[2] = CRCbit[3] ^ CRCTemp[0];
|
||||
CRCbit[3] = CRCbit[4] ^ CRCTemp[0];
|
||||
CRCbit[4] = CRCbit[5];
|
||||
CRCbit[5] = CRCbit[6];
|
||||
CRCbit[6] = CRCbit[7];
|
||||
CRCbit[7] = CRCTemp[0];
|
||||
}
|
||||
|
||||
CRCbit.CopyTo(CRCbyte, 0);
|
||||
return BitConverter.ToString(CRCbyte); ;
|
||||
}
|
||||
/// <summary>
|
||||
/// handles indenting and formatting for xml text
|
||||
/// </summary>
|
||||
/// <param name="XML"></param>
|
||||
/// <returns></returns>
|
||||
public static string PrettyPrint(string XML)
|
||||
{
|
||||
var Result = "";
|
||||
|
||||
using (var MS = new MemoryStream())
|
||||
{
|
||||
using (var W = new XmlTextWriter(MS, Encoding.Unicode))
|
||||
{
|
||||
var D = new XmlDocument();
|
||||
try
|
||||
{
|
||||
// Load the XmlDocument with the XML.
|
||||
D.LoadXml(XML);
|
||||
|
||||
W.Formatting = Formatting.Indented;
|
||||
|
||||
// Write the XML into a formatting XmlTextWriter
|
||||
D.WriteContentTo(W);
|
||||
W.Flush();
|
||||
MS.Flush();
|
||||
|
||||
// Have to rewind the MemoryStream in order to read
|
||||
// its contents.
|
||||
MS.Position = 0;
|
||||
|
||||
// Read MemoryStream contents into a StreamReader.
|
||||
using (var SR = new StreamReader(MS))
|
||||
{// Extract the text from the StreamReader.
|
||||
var FormattedXML = SR.ReadToEnd();
|
||||
Result = FormattedXML;
|
||||
}
|
||||
}
|
||||
catch (XmlException) { }
|
||||
|
||||
MS.Close();
|
||||
W.Close();
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
//https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-display-milliseconds-in-date-and-time-values
|
||||
//FB 29410 Format the date time to string with milliseonds
|
||||
/// <summary>
|
||||
/// Format a DateTime with nanoseconds part to a date time string with milliseconds in a current culture
|
||||
/// </summary>
|
||||
/// <param name="dateTimeWithNanoSeconds">DateTime object with nano seconds part</param>
|
||||
/// <returns>Formatted date time in string</returns>
|
||||
public static string FormatTimeStamp(DateTime dateTimeWithNanoSeconds)
|
||||
{
|
||||
string fullPattern = DateTimeFormatInfo.CurrentInfo.LongTimePattern;
|
||||
|
||||
// Create a format similar to .fff but based on the current culture.
|
||||
string millisecondFormat = $"{NumberFormatInfo.CurrentInfo.NumberDecimalSeparator}fff";
|
||||
|
||||
// Append millisecond pattern to current culture's full date time pattern.
|
||||
fullPattern = Regex.Replace(fullPattern, "(:ss|:s)", $"$1{millisecondFormat}");
|
||||
|
||||
string time = dateTimeWithNanoSeconds.ToString(fullPattern);
|
||||
string date = dateTimeWithNanoSeconds.ToShortDateString();
|
||||
string dateTime = $"{date} {time}";
|
||||
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// returns the next highest power of 2
|
||||
/// </summary>
|
||||
/// <param name="numSamples"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetEnclosingPower2(int numSamples)
|
||||
{
|
||||
//return Convert.ToInt32(Math.Pow(2D, Math.Ceiling(Math.Log(Convert.ToDouble(numSamples)) / Math.Log(2D))));
|
||||
// 24418 use bitwise calc for better performance
|
||||
var next = (uint)numSamples;
|
||||
next--;
|
||||
next |= next >> 1;
|
||||
next |= next >> 2;
|
||||
next |= next >> 4;
|
||||
next |= next >> 8;
|
||||
next |= next >> 16;
|
||||
next++;
|
||||
return (int)next;
|
||||
}
|
||||
public static long GetEnclosingPower2(long numSamples)
|
||||
{
|
||||
//return Convert.ToInt32(Math.Pow(2D, Math.Ceiling(Math.Log(Convert.ToDouble(numSamples)) / Math.Log(2D))));
|
||||
// 24418 use bitwise calc for better performance
|
||||
var next = (ulong)numSamples;
|
||||
next--;
|
||||
next |= next >> 1;
|
||||
next |= next >> 2;
|
||||
next |= next >> 4;
|
||||
next |= next >> 8;
|
||||
next |= next >> 16;
|
||||
next |= next >> 32;
|
||||
next++;
|
||||
return (long)next;
|
||||
}
|
||||
public static string EscapeString(string str)
|
||||
{
|
||||
if (null == str) { return "#NOVALUE"; }
|
||||
var mustQuote = (str.Contains(",") || str.Contains("\"") || str.Contains("\r") || str.Contains("\n"));
|
||||
if (!mustQuote) return str;
|
||||
var sb = new StringBuilder();
|
||||
sb.Append("\"");
|
||||
foreach (var nextChar in str)
|
||||
{
|
||||
sb.Append(nextChar);
|
||||
if (nextChar == '"') sb.Append("\"");
|
||||
}
|
||||
sb.Append("\"");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string ReplaceLast(this string str, string find, string replace)
|
||||
{
|
||||
var place = str.LastIndexOf(find, StringComparison.Ordinal);
|
||||
return -1 == place
|
||||
? str
|
||||
: str.Remove(place, find.Length).Insert(place, replace);
|
||||
}
|
||||
public static string ReplaceFirst(this string str, string find, string replace)
|
||||
{
|
||||
var place = str.IndexOf(find, StringComparison.Ordinal);
|
||||
return -1 == place
|
||||
? str
|
||||
: str.Remove(place, find.Length).Insert(place, replace);
|
||||
}
|
||||
public static string ReplaceStrings(this string str, Dictionary<string, string> toReplace, Common.Enums.StringReplacementMode mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case StringReplacementMode.All:
|
||||
toReplace.ForEach(pair => str = str.Replace(pair.Key, pair.Value));
|
||||
break;
|
||||
case StringReplacementMode.First:
|
||||
toReplace.ForEach(pair => str = str.ReplaceFirst(pair.Key, pair.Value));
|
||||
break;
|
||||
case StringReplacementMode.Last:
|
||||
toReplace.ForEach(pair => str = str.ReplaceLast(pair.Key, pair.Value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored, bad data in
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
public static void GetChildren(UIElement parent, Type targetType, ref List<UIElement> children)
|
||||
{
|
||||
var count = VisualTreeHelper.GetChildrenCount(parent);
|
||||
if (count <= 0) return;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var child = (UIElement)VisualTreeHelper.GetChild(parent, i);
|
||||
if (child.GetType() == targetType) { children.Add(child); }
|
||||
|
||||
GetChildren(child, targetType, ref children);
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetChildrenByName(UIElement parent, string targetName, ref List<FrameworkElement> children)
|
||||
{
|
||||
var count = VisualTreeHelper.GetChildrenCount(parent);
|
||||
if (count <= 0) return;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var child = (UIElement)VisualTreeHelper.GetChild(parent, i);
|
||||
if (((string)child.GetType().GetProperty("Name").GetValue(child, null)).Contains(targetName)) { children.Add((FrameworkElement)child); }
|
||||
|
||||
GetChildrenByName(child, targetName, ref children);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a Child of a given item in the visual tree.
|
||||
/// </summary>
|
||||
/// <param name="parent">A direct parent of the queried item.</param>
|
||||
/// <typeparam name="T">The type of the queried item.</typeparam>
|
||||
/// <param name="childName">x:Name or Name of child. </param>
|
||||
/// <returns>The first parent item that matches the submitted type parameter.
|
||||
/// If not matching item can be found,
|
||||
/// a null parent is being returned.</returns>
|
||||
public static T FindChild<T>(DependencyObject parent, string childName)
|
||||
where T : DependencyObject
|
||||
{
|
||||
// Confirm parent and childName are valid.
|
||||
if (parent == null) return null;
|
||||
|
||||
T foundChild = null;
|
||||
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
// If the child is not of the request child type child
|
||||
if (!(child is T))
|
||||
{
|
||||
// recursively drill down the tree
|
||||
foundChild = FindChild<T>(child, childName);
|
||||
|
||||
// If the child is found, break so we do not overwrite the found child.
|
||||
if (foundChild != null) break;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(childName))
|
||||
{
|
||||
// If the child's name is set for search
|
||||
if (child is FrameworkElement frameworkElement && frameworkElement.Name == childName)
|
||||
{
|
||||
// if the child's name is of the request name
|
||||
foundChild = (T)child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// child element found.
|
||||
foundChild = (T)child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return foundChild;
|
||||
}
|
||||
|
||||
public static T FindParent<T>(DependencyObject child)
|
||||
where T : DependencyObject
|
||||
{
|
||||
if (null == child) return null;
|
||||
T visParent = VisualTreeHelper.GetParent(child) as T;
|
||||
T logParent = LogicalTreeHelper.GetParent(child) as T;
|
||||
|
||||
return visParent ?? logParent ?? FindParent<T>(VisualTreeHelper.GetParent(child));
|
||||
}
|
||||
|
||||
public static T FindVisualChild<T>(DependencyObject obj)
|
||||
where T : DependencyObject
|
||||
{
|
||||
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||||
if (child is T variable)
|
||||
return variable;
|
||||
var childOfChild = FindVisualChild<T>(child);
|
||||
if (childOfChild != null)
|
||||
return childOfChild;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<T> GetVisualChildren<T>(DependencyObject obj) where T : DependencyObject
|
||||
{
|
||||
var childList = new List<T>();
|
||||
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
|
||||
if (child is T)
|
||||
childList.Add(child as T);
|
||||
}
|
||||
return childList.Count > 0 ? childList : null;
|
||||
}
|
||||
|
||||
|
||||
public static string GetEnumDescription<T>(this T enumerationValue) where T : struct
|
||||
{
|
||||
var type = enumerationValue.GetType();
|
||||
if (!type.IsEnum)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(enumerationValue)} must be of Enum type", nameof(enumerationValue));
|
||||
}
|
||||
var memberInfo = type.GetMember(enumerationValue.ToString());
|
||||
if (memberInfo.Length > 0)
|
||||
{
|
||||
var attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
|
||||
|
||||
if (attrs.Length > 0)
|
||||
{
|
||||
return ((DescriptionAttribute)attrs[0]).Description;
|
||||
}
|
||||
}
|
||||
return enumerationValue.ToString();
|
||||
}
|
||||
|
||||
public static int FindValueInArray(double value, double[] valueArray)
|
||||
{
|
||||
for (var index = 0; index < valueArray.Length; index++)
|
||||
{
|
||||
if (value == valueArray[index])
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static double StandardDeviation(this IEnumerable<double> values)
|
||||
{
|
||||
var avg = values.Average();
|
||||
return Math.Sqrt(values.Average(val => (val - avg) * (val - avg)));
|
||||
}
|
||||
|
||||
public static void CalculateClip(double[] data,
|
||||
out double clipPeak,
|
||||
out double clipStartSeconds,
|
||||
out double clipEndSeconds,
|
||||
double sampleRate,
|
||||
int preZeroDataPoints)
|
||||
{
|
||||
|
||||
clipPeak = 0;
|
||||
clipStartSeconds = 0;
|
||||
clipEndSeconds = 0;
|
||||
|
||||
/* From TDC */
|
||||
for (var index = 0; index < data.Length - Math.Floor(0.003 / (1 / sampleRate) + 0.5); index++)
|
||||
{
|
||||
var localclip = 10000D;
|
||||
|
||||
for (var localIndex = index; localIndex < index + Math.Floor(0.003 / (1 / sampleRate) + 0.5); localIndex++)
|
||||
{
|
||||
if (data[localIndex] < localclip)
|
||||
{
|
||||
localclip = data[localIndex];
|
||||
}
|
||||
}
|
||||
|
||||
if (!(localclip > clipPeak)) continue;
|
||||
clipPeak = localclip;
|
||||
clipStartSeconds = (index - preZeroDataPoints) * (1 / sampleRate);
|
||||
clipEndSeconds = clipStartSeconds + 0.003;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly short[] ODDPARITY = {0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0 };
|
||||
|
||||
public static byte Math_CRC7(byte[] buffer, int length)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
byte crc = 0xFF;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
var currentByte = buffer[i];
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
crc = (byte)(crc << 1);
|
||||
if (0x00 != ((currentByte ^ crc) & 0x80))
|
||||
{
|
||||
crc = (byte)(crc ^ 0x09);
|
||||
}
|
||||
|
||||
currentByte <<= 1;
|
||||
}
|
||||
|
||||
crc = (byte)(crc & 0x7F);
|
||||
}
|
||||
|
||||
crc <<= 1;
|
||||
crc |= 0x01;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the 16-bit CRC of the n passed in data bytes. N should be
|
||||
* even (if it is not, the last byte will not get included in the
|
||||
* computation). The initial_crc is the value to seed the computation
|
||||
* from - normally it will be set to 0.
|
||||
*
|
||||
* @param data the unsigned character buffer of which to compute the CRC16
|
||||
* @param n the number of bytes in data (must be even!)
|
||||
* @param initial_crc the CRC16 value to seed the computation with
|
||||
*
|
||||
* @return the updated CRC16 starting with initial_crc and computed over
|
||||
* n data bytes
|
||||
*/
|
||||
/* Slightly changed to handle array of bytes */
|
||||
public static ushort CalculateCRC(byte[] data, ushort initialCRC)
|
||||
{
|
||||
|
||||
ushort crc = 0;//initial_crc98765430.
|
||||
int i;
|
||||
|
||||
for (i = 0; i < data.Length; i += 2)
|
||||
{
|
||||
crc = Math_DoCRC16Step((ushort)((data[i + 1] << 8) | data[i]), crc);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the 16-bit CRC of the n passed in data bytes. CCITT implementation
|
||||
* N should be
|
||||
* even (if it is not, the last byte will not get included in the
|
||||
* computation). The initial_crc is the value to seed the computation
|
||||
* from - normally it will be set to 0.
|
||||
*
|
||||
* @param data the unsigned character buffer of which to compute the CRC16
|
||||
* @param n the number of bytes in data (must be even!)
|
||||
* @param initial_crc the CRC16 value to seed the computation with
|
||||
*
|
||||
* @return the updated CRC16 starting with initial_crc and computed over
|
||||
* n data bytes
|
||||
*/
|
||||
/* Slightly changed to handle array of bytes */
|
||||
public static ushort CalculateCRCCCITT(byte[] data, ushort initialCRC)
|
||||
{
|
||||
|
||||
var crc = initialCRC;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < data.Length; i += 2)
|
||||
{
|
||||
crc = Math_DoCRCCCITTStep((ushort)((data[i + 1] << 8) | data[i]), crc);
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
public static ushort Math_DoCRC16Step(ushort cdata, ushort currentCRC)
|
||||
{
|
||||
cdata = (ushort)((cdata ^ (currentCRC & 0xff)) & 0xff);
|
||||
currentCRC >>= 8;
|
||||
|
||||
if (0 != (ODDPARITY[cdata & 0xf] ^ ODDPARITY[cdata >> 4]))
|
||||
currentCRC ^= 0xc001;
|
||||
|
||||
cdata <<= 6;
|
||||
currentCRC ^= cdata;
|
||||
cdata <<= 1;
|
||||
currentCRC ^= cdata;
|
||||
|
||||
return currentCRC;
|
||||
}
|
||||
|
||||
private static readonly ushort[] CRC_TABLE =
|
||||
{
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5,
|
||||
0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b,
|
||||
0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210,
|
||||
0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c,
|
||||
0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
|
||||
0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,
|
||||
0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6,
|
||||
0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738,
|
||||
0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5,
|
||||
0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969,
|
||||
0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96,
|
||||
0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,
|
||||
0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03,
|
||||
0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
|
||||
0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6,
|
||||
0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
|
||||
0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb,
|
||||
0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1,
|
||||
0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c,
|
||||
0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2,
|
||||
0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb,
|
||||
0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447,
|
||||
0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
|
||||
0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2,
|
||||
0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9,
|
||||
0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827,
|
||||
0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c,
|
||||
0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0,
|
||||
0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d,
|
||||
0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,
|
||||
0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba,
|
||||
0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
|
||||
0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
public static ushort Math_DoCRCCCITTStep(ushort cdata, ushort current_crc)
|
||||
{
|
||||
return (ushort)((ushort)(current_crc << 8) ^ CRC_TABLE[(ushort)(((ushort)(current_crc >> 8) ^ cdata) & 0xFF)]);
|
||||
}
|
||||
|
||||
public static void FilterDataArray(ref double[] data, double sampleRate, double filterFrequency)
|
||||
{
|
||||
/********************************/
|
||||
/*** MCW NHTSA FILTER ROUTINE ***/
|
||||
/********************************/
|
||||
|
||||
//
|
||||
// CFILTER.C cfc filter program
|
||||
//
|
||||
// Filters data using SAE J211 algorithym (4 pole phaseless lo pass).
|
||||
// "Pads" data with 5% of the original number of points at the beginning with the first point
|
||||
// and 5% of the original number of points at the end with the last point
|
||||
// to "squelch" out filter start up spikes.
|
||||
// Previously read data file from disc, filtered and wrote new data file to disc.
|
||||
// NOW read/writes to array(s) in memory.
|
||||
// Optionally zeros baseline by subtracting the average of the first 5%
|
||||
// of the original number of points; SKIPS data which is "padded" by this routine
|
||||
// Optionally scales the data after filtering. SCALE = 1.0 skips to avoid unnecessary calc's.
|
||||
//
|
||||
// "syntax:"
|
||||
//
|
||||
// cfilter(INdata, SCALE, OUTdata, SampleRate, CFCnumb, BaseLine, NumPoints);
|
||||
//
|
||||
// INdata (pointer?): array (double) of data to be filtered
|
||||
// SCALE (double): a number multiplied by the above array after it is filtered.
|
||||
// Useful for "last minute" scaling and/or inversion
|
||||
// Outdata (pointer?): array (double) into which the results are stored.
|
||||
// INdata can = OUTdata, INdata will then be overwrittten.
|
||||
// SampleRate (double): the frequency(in samples per second) at which the INdata were sampled.
|
||||
// CFCnumb (double): SAE Channel Filter Class;
|
||||
// 60, 180, 600, or 1000; ONLY these values have been validated.
|
||||
// BaseLine (char): a single character; ONLY "Y" or "y" will zero baseline;
|
||||
// (This started as a command line style FORTRAN program and used to "ask"
|
||||
// the user. Some day this should be changed to an integer (1 or 0) switch.)
|
||||
// NumPoints (int): the number of points in the input array (INdata);
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// int cfilter(double *indata, double calib, double *out, double freq,
|
||||
// double cfc, char baseline[2], int n)
|
||||
// {
|
||||
double[] Z;
|
||||
double[] A;
|
||||
double t, pi, wd, wa, d0, d1, d2, e1, e2;
|
||||
double f1, f2, f3, f4, f5;
|
||||
int data_end, i, j, k, pad;
|
||||
double[] NewDataArray;
|
||||
var calib = 1.0;
|
||||
var CFC = filterFrequency * 0.6;
|
||||
|
||||
// The set-up of the formulas.
|
||||
|
||||
t = 1.0 / sampleRate;
|
||||
pi = 4.0 * Math.Atan(1.0);
|
||||
wd = 2.0 * pi * CFC * 2.0775;
|
||||
wa = Math.Sin(wd * (t / 2.0)) / Math.Cos(wd * (t / 2.0)); // The original formula
|
||||
d0 = wa * wa / (1 + Math.Sqrt(2.0) * wa + wa * wa);
|
||||
d1 = 2.0 * d0;
|
||||
d2 = d0;
|
||||
e1 = -2.0 * (wa * wa - 1) / (1 + Math.Sqrt(2.0) * wa + wa * wa);
|
||||
e2 = (-1 + Math.Sqrt(2.0) * wa - wa * wa) / (1 + Math.Sqrt(2.0) * wa + wa * wa);
|
||||
|
||||
data_end = data.Length - 1; // data_end is used for loop counting corresponding
|
||||
// to the number of lines that the data file has
|
||||
pad = (int)(0.05 * data.Length);
|
||||
Z = new double[pad + pad + data.Length];
|
||||
A = new double[pad + pad + data.Length];
|
||||
NewDataArray = new double[pad + pad + data.Length];
|
||||
|
||||
for (i = 0; i <= pad - 1; i++) // pad newdata at beginning
|
||||
{ // w/ first pt of indata
|
||||
NewDataArray[i] = data[i];
|
||||
}
|
||||
|
||||
for (i = pad; i <= data_end + pad - 1; i++) // Copy indata into newdata
|
||||
{ // after initial pad
|
||||
NewDataArray[i] = data[i - (pad - 1)];
|
||||
}
|
||||
|
||||
for (i = data_end + pad; i <= data_end + 2 * pad - 1; i++) // pad newdata at end
|
||||
{ // w/ last pt of indata
|
||||
NewDataArray[i] = data[data_end - 1];
|
||||
}
|
||||
|
||||
data_end = data_end + 2 * pad;
|
||||
|
||||
// Data Passed Through Filter Backward
|
||||
|
||||
for (j = data_end - 2; j >= 0; j--)
|
||||
{
|
||||
f1 = d0 * NewDataArray[j]; // Breaking
|
||||
f2 = d1 * NewDataArray[j + 1]; // down
|
||||
f3 = d2 * NewDataArray[j + 2]; // a big
|
||||
f4 = e1 * Z[j + 1]; // formula
|
||||
f5 = e2 * Z[j + 2]; // into smaller "groups".
|
||||
Z[j] = f1 + f2 + f3 + f4 + f5; // Putting the "groups" back together
|
||||
}
|
||||
Z[data_end - 1] = Z[data_end - 3];
|
||||
Z[data_end - 2] = Z[data_end - 3];
|
||||
|
||||
// Data Passed Through Filter Forward
|
||||
|
||||
for (k = 3; k <= data_end; k++)
|
||||
{
|
||||
f1 = d0 * Z[k]; // Breaking
|
||||
f2 = d1 * Z[k - 1]; // down
|
||||
f3 = d2 * Z[k - 2]; // a big
|
||||
f4 = e1 * A[k - 1]; // formula
|
||||
f5 = e2 * A[k - 2]; // into smaller "groups".
|
||||
A[k] = f1 + f2 + f3 + f4 + f5; // Putting the "groups" back together
|
||||
}
|
||||
A[1] = A[3]; // This sets the first data points to the same
|
||||
A[2] = A[3]; // value as the 3rd value. Without this, the
|
||||
|
||||
i = 0;
|
||||
for (k = pad; k <= data_end - pad; k++) // DO loop to write output file
|
||||
{
|
||||
if (calib != 1.0) //
|
||||
{ // Multiplying by the calibration factor
|
||||
A[k] = A[k] * calib; // Unless factor = 1.0
|
||||
} // AFTER the filtering has been finished
|
||||
|
||||
NewDataArray[i] = A[k];
|
||||
i++;
|
||||
}
|
||||
|
||||
Array.Copy(NewDataArray, 0, data, 0, data.Length);
|
||||
|
||||
}
|
||||
|
||||
public static bool IsLike(string text, string pattern, bool caseSensitive = false)
|
||||
{
|
||||
//Check for empties
|
||||
if (string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(pattern)) return true;
|
||||
|
||||
//Prepare for regex
|
||||
pattern = pattern.Replace(".", @"\.");
|
||||
pattern = pattern.Replace("(", @"\(");
|
||||
pattern = pattern.Replace(")", @"\)");
|
||||
pattern = pattern.Replace("?", ".");
|
||||
//pattern = pattern.Replace("*", ".*?");
|
||||
pattern = pattern.Replace(@"\", @"\\");
|
||||
pattern = pattern.Replace(" ", @"\s");
|
||||
try
|
||||
{
|
||||
return new Regex(pattern, caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase).IsMatch(text);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool? IsClockSynced(IDictionary<InputClockSource, bool> clocksyncs, ClockSyncProfile profile, HardwareTypes hwType)
|
||||
{
|
||||
if (HardwareTypes.SLICE_Pro_Distributor == hwType) { return null; }
|
||||
if ( HardwareTypes.SLICE6DB3 == hwType) { return null; }
|
||||
if ((HardwareTypes.SLICE6_Base == hwType || HardwareTypes.SLICE6DB == hwType || HardwareTypes.SLICE6DB_InDummy == hwType) && profile == ClockSyncProfile.Manual)
|
||||
{
|
||||
//18030 S6, S6DB can only do PTP so "manual" is always PTP
|
||||
profile = ClockSyncProfile.Auto_E2E;
|
||||
}
|
||||
bool? synced = null;
|
||||
switch (profile)
|
||||
{
|
||||
case ClockSyncProfile.Master_E2E:
|
||||
break;
|
||||
case ClockSyncProfile.Auto_E2E:
|
||||
case ClockSyncProfile.Slave_E2E:
|
||||
synced = clocksyncs[InputClockSource.PTP];
|
||||
break;
|
||||
case ClockSyncProfile.EXT_PPS:
|
||||
case ClockSyncProfile.Master_E2E_EXT_PPS:
|
||||
synced = clocksyncs[InputClockSource.OnePPS];
|
||||
break;
|
||||
case ClockSyncProfile.GPS:
|
||||
case ClockSyncProfile.Master_E2E_GPS:
|
||||
synced = clocksyncs[InputClockSource.GPS];
|
||||
break;
|
||||
case ClockSyncProfile.IRIG:
|
||||
case ClockSyncProfile.Master_E2E_IRIG:
|
||||
synced = clocksyncs[InputClockSource.IRIG];
|
||||
break;
|
||||
case ClockSyncProfile.GPS_EXT_PPS:
|
||||
case ClockSyncProfile.Master_E2E_GPS_EXT_PPS:
|
||||
synced = clocksyncs[InputClockSource.GPS] &&
|
||||
clocksyncs[InputClockSource.OnePPS];
|
||||
break;
|
||||
case ClockSyncProfile.IRIG_EXT_PPS:
|
||||
case ClockSyncProfile.Master_E2E_IRIG_EXT_PPS:
|
||||
synced = clocksyncs[InputClockSource.IRIG] &&
|
||||
clocksyncs[InputClockSource.OnePPS];
|
||||
break;
|
||||
}
|
||||
return synced;
|
||||
}
|
||||
|
||||
public static bool IsTmNSString(string tmns)
|
||||
{
|
||||
return tmns.StartsWith("(") &&
|
||||
tmns.EndsWith(")") &&
|
||||
tmns.TrimStart(new[] { '(' }).TrimEnd(new[] { ')' }).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).All(sval => uint.TryParse(sval, out var uval) && uval < 65536);
|
||||
}
|
||||
|
||||
const double _1 = 0.1;
|
||||
const double _2 = 0.01;
|
||||
const double _3 = 0.001;
|
||||
const double _4 = 0.0001;
|
||||
const double _5 = 0.00001;
|
||||
const double _6 = 0.000001;
|
||||
const double _7 = 0.0000001;
|
||||
public static bool EqualsDigitPrecision(this double left, double right, uint precision)
|
||||
{
|
||||
var diff = Math.Abs(left - right);
|
||||
switch(precision)
|
||||
{
|
||||
case 0:
|
||||
return (int)left == (int)right;
|
||||
case 1:
|
||||
return diff < _1;
|
||||
case 2:
|
||||
return diff < _2;
|
||||
case 3:
|
||||
return diff < _3;
|
||||
case 4:
|
||||
return diff < _4;
|
||||
case 5:
|
||||
return diff < _5;
|
||||
case 6:
|
||||
return diff < _6;
|
||||
default:
|
||||
case 7:
|
||||
return diff < _7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using DTS.Common.Interface.Hardware;
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
// ReSharper disable PossibleNullReferenceException
|
||||
|
||||
namespace DTS.Common.Converters
|
||||
{
|
||||
public class DASStatusColorConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (value is DASStatuses status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case DASStatuses.MissingNotBooted:
|
||||
return BrushesAndColors.Brush_ApplicationStatus_Idle;
|
||||
case DASStatuses.BootedNotArmedYet:
|
||||
return BrushesAndColors.Brush_ApplicationStatus_Busy;
|
||||
case DASStatuses.BootedNeverArmed:
|
||||
return BrushesAndColors.Brush_ApplicationStatus_Failed;
|
||||
case DASStatuses.ArmedReady:
|
||||
return BrushesAndColors.Brush_ApplicationStatus_Complete;
|
||||
case DASStatuses.ArmedButFailedDiag:
|
||||
return BrushesAndColors.Brush_ApplicationStatus_Failed;
|
||||
case DASStatuses.ReadyForDownload:
|
||||
return BrushesAndColors.Brush_ApplicationStatus_Complete;
|
||||
}
|
||||
}
|
||||
return BrushesAndColors.Brush_ApplicationStatus_Idle;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
return value.Equals(true) ? parameter : Binding.DoNothing;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user