更新曲线数据
This commit is contained in:
@@ -29,6 +29,12 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
private const double SampleIntervalSeconds = 1.0 / 50.0;
|
private const double SampleIntervalSeconds = 1.0 / 50.0;
|
||||||
private const double DynamicWindowStartSeconds = 0.3;
|
private const double DynamicWindowStartSeconds = 0.3;
|
||||||
private const double DynamicWindowEndSeconds = 0.6;
|
private const double DynamicWindowEndSeconds = 0.6;
|
||||||
|
private const double StaticPeakSearchEndSeconds = DynamicWindowEndSeconds;
|
||||||
|
private const double StaticPeakMinimumRiseN = 1.0;
|
||||||
|
private const double StaticPeakDropToleranceN = 0.5;
|
||||||
|
private const double SlidingStartDisplacementThresholdMm = 0.05;
|
||||||
|
private const double MinimumAnalysisLoadRatio = 0.8;
|
||||||
|
private const int StaticPeakDropConfirmationPointCount = 3;
|
||||||
private const int MinimumDynamicWindowPointCount = 10;
|
private const int MinimumDynamicWindowPointCount = 10;
|
||||||
private const int StandardTrialCount = 3;
|
private const int StandardTrialCount = 3;
|
||||||
private const string DefaultPlcPortName = "COM3";
|
private const string DefaultPlcPortName = "COM3";
|
||||||
@@ -58,6 +64,8 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
private int activeBaudRate;
|
private int activeBaudRate;
|
||||||
private List<SlipDataPoint> lastCompletedRun = [];
|
private List<SlipDataPoint> lastCompletedRun = [];
|
||||||
private DateTime lastRealtimeCurveTraceLoggedAt = DateTime.MinValue;
|
private DateTime lastRealtimeCurveTraceLoggedAt = DateTime.MinValue;
|
||||||
|
private double runStartDisplacementMm;
|
||||||
|
private double? slidingStartTimeSeconds;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string testNumber = $"SLIP-{DateTime.Now:yyyyMMdd-HHmm}";
|
private string testNumber = $"SLIP-{DateTime.Now:yyyyMMdd-HHmm}";
|
||||||
@@ -672,11 +680,18 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
horizontalFrictionPoints.Clear();
|
horizontalFrictionPoints.Clear();
|
||||||
frictionCoefficientPoints.Clear();
|
frictionCoefficientPoints.Clear();
|
||||||
displacementPoints.Clear();
|
displacementPoints.Clear();
|
||||||
|
runStartDisplacementMm = deviceService.CurrentSnapshot.DisplacementMm;
|
||||||
|
slidingStartTimeSeconds = null;
|
||||||
runStopwatch.Restart();
|
runStopwatch.Restart();
|
||||||
UploadProgress = 0;
|
UploadProgress = 0;
|
||||||
lastRealtimeCurveTraceLoggedAt = DateTime.MinValue;
|
lastRealtimeCurveTraceLoggedAt = DateTime.MinValue;
|
||||||
CurrentStatus = "测试运行:按标准采集垂直载荷、摩擦力、位移与摩擦系数";
|
CurrentStatus = "测试运行:按标准采集垂直载荷、摩擦力、位移与摩擦系数";
|
||||||
Log.Information("测试开始:TestNumber={TestNumber}, TargetLoad={TargetLoad}, TestSpeed={TestSpeed}", TestNumber, TargetLoadText, TestSpeedText);
|
Log.Information(
|
||||||
|
"测试开始:TestNumber={TestNumber}, TargetLoad={TargetLoad}, TestSpeed={TestSpeed}, StartDisplacement={StartDisplacement:F3}mm",
|
||||||
|
TestNumber,
|
||||||
|
TargetLoadText,
|
||||||
|
TestSpeedText,
|
||||||
|
runStartDisplacementMm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordPoint(SlipDeviceSnapshot device)
|
private void RecordPoint(SlipDeviceSnapshot device)
|
||||||
@@ -695,6 +710,7 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
device.DisplacementMm,
|
device.DisplacementMm,
|
||||||
device.FrictionCoefficient);
|
device.FrictionCoefficient);
|
||||||
|
|
||||||
|
TryMarkSlidingStart(point);
|
||||||
currentRun.Add(point);
|
currentRun.Add(point);
|
||||||
verticalLoadPoints.Add(new ObservablePoint(time, point.VerticalLoadN));
|
verticalLoadPoints.Add(new ObservablePoint(time, point.VerticalLoadN));
|
||||||
horizontalFrictionPoints.Add(new ObservablePoint(time, point.HorizontalFrictionN));
|
horizontalFrictionPoints.Add(new ObservablePoint(time, point.HorizontalFrictionN));
|
||||||
@@ -717,22 +733,43 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastCompletedRun = currentRun.ToList();
|
lastCompletedRun = currentRun.ToList();
|
||||||
var peak = FindStaticPeak(currentRun);
|
var minimumAnalysisLoad = GetMinimumAnalysisLoad();
|
||||||
|
if (!TryFindSlidingStart(currentRun, runStartDisplacementMm, minimumAnalysisLoad, out var slidingStartPoint))
|
||||||
|
{
|
||||||
|
Log.Warning(
|
||||||
|
"测试停止但未检测到有效滑动开始:TestNumber={TestNumber}, PointCount={PointCount}, StartDisplacement={StartDisplacement:F3}mm, DisplacementThreshold={DisplacementThreshold:F3}mm, MinimumAnalysisLoad={MinimumAnalysisLoad:F3}N, FirstSample={FirstSample}, LastSample={LastSample}",
|
||||||
|
TestNumber,
|
||||||
|
currentRun.Count,
|
||||||
|
runStartDisplacementMm,
|
||||||
|
SlidingStartDisplacementThresholdMm,
|
||||||
|
minimumAnalysisLoad,
|
||||||
|
FormatDataPoint(currentRun[0]),
|
||||||
|
FormatDataPoint(currentRun[^1]));
|
||||||
|
CurrentStatus = "测试已停止,但未检测到有效滑动开始,未生成结果";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var slidingStartTime = slidingStartPoint.TimeSeconds;
|
||||||
|
var staticPeak = FindStaticPeak(currentRun, slidingStartTime);
|
||||||
|
var peak = staticPeak.Point;
|
||||||
|
var dynamicWindowStart = slidingStartTime + DynamicWindowStartSeconds;
|
||||||
|
var dynamicWindowEnd = slidingStartTime + DynamicWindowEndSeconds;
|
||||||
var dynamicWindow = currentRun
|
var dynamicWindow = currentRun
|
||||||
.Where(point => point.TimeSeconds >= DynamicWindowStartSeconds && point.TimeSeconds <= DynamicWindowEndSeconds)
|
.Where(point => point.TimeSeconds >= dynamicWindowStart && point.TimeSeconds <= dynamicWindowEnd)
|
||||||
.ToList();
|
.ToList();
|
||||||
if (dynamicWindow.Count < MinimumDynamicWindowPointCount)
|
if (dynamicWindow.Count < MinimumDynamicWindowPointCount)
|
||||||
{
|
{
|
||||||
var firstWindowPoint = dynamicWindow.FirstOrDefault();
|
var firstWindowPoint = dynamicWindow.FirstOrDefault();
|
||||||
var lastWindowPoint = dynamicWindow.LastOrDefault();
|
var lastWindowPoint = dynamicWindow.LastOrDefault();
|
||||||
Log.Warning(
|
Log.Warning(
|
||||||
"测试停止但动摩擦窗口采样点不足:TestNumber={TestNumber}, PointCount={PointCount}, DynamicWindow=0.300-0.600s, DynamicWindowPointCount={DynamicWindowPointCount}, RequiredPointCount={RequiredPointCount}, ActualWindowStart={ActualWindowStart}, ActualWindowEnd={ActualWindowEnd}, FirstSampleTime={FirstSampleTime:F3}s, LastSampleTime={LastSampleTime:F3}s",
|
"测试停止但动摩擦窗口采样点不足:TestNumber={TestNumber}, PointCount={PointCount}, SlidingStartTime={SlidingStartTime:F3}s, DynamicWindow=滑动开始后0.300-0.600s, DynamicWindowPointCount={DynamicWindowPointCount}, RequiredPointCount={RequiredPointCount}, ActualWindowStart={ActualWindowStart}, ActualWindowEnd={ActualWindowEnd}, FirstSampleTime={FirstSampleTime:F3}s, LastSampleTime={LastSampleTime:F3}s",
|
||||||
TestNumber,
|
TestNumber,
|
||||||
currentRun.Count,
|
currentRun.Count,
|
||||||
|
slidingStartTime,
|
||||||
dynamicWindow.Count,
|
dynamicWindow.Count,
|
||||||
MinimumDynamicWindowPointCount,
|
MinimumDynamicWindowPointCount,
|
||||||
FormatNullable(firstWindowPoint?.TimeSeconds),
|
FormatRelativeTime(firstWindowPoint, slidingStartTime),
|
||||||
FormatNullable(lastWindowPoint?.TimeSeconds),
|
FormatRelativeTime(lastWindowPoint, slidingStartTime),
|
||||||
currentRun[0].TimeSeconds,
|
currentRun[0].TimeSeconds,
|
||||||
currentRun[^1].TimeSeconds);
|
currentRun[^1].TimeSeconds);
|
||||||
CurrentStatus = "测试已停止,0.3 s~0.6 s 有效采样点不足,未生成结果";
|
CurrentStatus = "测试已停止,0.3 s~0.6 s 有效采样点不足,未生成结果";
|
||||||
@@ -742,20 +779,38 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
var staticCoefficientValue = CalculateCoefficient(peak.HorizontalFrictionN, peak.VerticalLoadN);
|
var staticCoefficientValue = CalculateCoefficient(peak.HorizontalFrictionN, peak.VerticalLoadN);
|
||||||
var dynamicForce = dynamicWindow.Average(point => point.HorizontalFrictionN);
|
var dynamicForce = dynamicWindow.Average(point => point.HorizontalFrictionN);
|
||||||
var dynamicLoad = dynamicWindow.Average(point => point.VerticalLoadN);
|
var dynamicLoad = dynamicWindow.Average(point => point.VerticalLoadN);
|
||||||
|
if (peak.VerticalLoadN < minimumAnalysisLoad || dynamicLoad < minimumAnalysisLoad)
|
||||||
|
{
|
||||||
|
Log.Warning(
|
||||||
|
"测试停止但静/动摩擦窗口载荷不足:TestNumber={TestNumber}, SlidingStartTime={SlidingStartTime:F3}s, MinimumAnalysisLoad={MinimumAnalysisLoad:F3}N, StaticLoad={StaticLoad:F3}N, DynamicAvgLoad={DynamicAvgLoad:F3}N, StaticPoint={StaticPoint}, DynamicPointCount={DynamicPointCount}",
|
||||||
|
TestNumber,
|
||||||
|
slidingStartTime,
|
||||||
|
minimumAnalysisLoad,
|
||||||
|
peak.VerticalLoadN,
|
||||||
|
dynamicLoad,
|
||||||
|
FormatDataPoint(peak),
|
||||||
|
dynamicWindow.Count);
|
||||||
|
CurrentStatus = "测试已停止,静/动摩擦窗口载荷不足,未生成结果";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var dynamicCoefficientValue = CalculateCoefficient(dynamicForce, dynamicLoad);
|
var dynamicCoefficientValue = CalculateCoefficient(dynamicForce, dynamicLoad);
|
||||||
var verdict = NeedsRetest(staticCoefficientValue, dynamicCoefficientValue) ? "需重测" : "有效";
|
var verdict = NeedsRetest(staticCoefficientValue, dynamicCoefficientValue) ? "需重测" : "有效";
|
||||||
var nextIndex = Samples.Count == 0 ? 1 : Samples.Max(sample => sample.Index) + 1;
|
var nextIndex = Samples.Count == 0 ? 1 : Samples.Max(sample => sample.Index) + 1;
|
||||||
var peakIndex = currentRun.IndexOf(peak) + 1;
|
var peakIndex = currentRun.IndexOf(peak) + 1;
|
||||||
var dynamicStart = dynamicWindow[0].TimeSeconds;
|
var dynamicStart = dynamicWindow[0].TimeSeconds - slidingStartTime;
|
||||||
var dynamicEnd = dynamicWindow[^1].TimeSeconds;
|
var dynamicEnd = dynamicWindow[^1].TimeSeconds - slidingStartTime;
|
||||||
|
|
||||||
Log.Information(
|
Log.Information(
|
||||||
"静/动摩擦计算明细:TestNumber={TestNumber}, PointCount={PointCount}, StaticSearchWindow=0.000-{StaticSearchEnd:F3}s, StaticPointIndex={StaticPointIndex}, StaticTime={StaticTime:F3}s, StaticFriction={StaticFriction:F3}N, StaticLoad={StaticLoad:F3}N, StaticCoefficient={StaticCoefficient:F5}, DynamicWindow={DynamicWindowStart:F3}-{DynamicWindowEnd:F3}s, DynamicActualWindow={DynamicActualStart:F3}-{DynamicActualEnd:F3}s, DynamicPointCount={DynamicPointCount}, DynamicAvgFriction={DynamicAvgFriction:F3}N, DynamicAvgLoad={DynamicAvgLoad:F3}N, DynamicCoefficient={DynamicCoefficient:F5}",
|
"静/动摩擦计算明细:TestNumber={TestNumber}, PointCount={PointCount}, SlidingStartTime={SlidingStartTime:F3}s, SlidingStartDisplacement={SlidingStartDisplacement:F3}mm, StaticSearchWindow=滑动开始后首个峰值0.000-{StaticSearchEnd:F3}s, StaticPeakMode={StaticPeakMode}, StaticPointIndex={StaticPointIndex}, StaticTime={StaticTime:F3}s, StaticFriction={StaticFriction:F3}N, StaticLoad={StaticLoad:F3}N, StaticCoefficient={StaticCoefficient:F5}, DynamicWindow=滑动开始后{DynamicWindowStart:F3}-{DynamicWindowEnd:F3}s, DynamicActualWindow={DynamicActualStart:F3}-{DynamicActualEnd:F3}s, DynamicPointCount={DynamicPointCount}, DynamicAvgFriction={DynamicAvgFriction:F3}N, DynamicAvgLoad={DynamicAvgLoad:F3}N, DynamicCoefficient={DynamicCoefficient:F5}",
|
||||||
TestNumber,
|
TestNumber,
|
||||||
currentRun.Count,
|
currentRun.Count,
|
||||||
DynamicWindowStartSeconds,
|
slidingStartTime,
|
||||||
|
slidingStartPoint.DisplacementMm,
|
||||||
|
StaticPeakSearchEndSeconds,
|
||||||
|
staticPeak.Mode,
|
||||||
peakIndex,
|
peakIndex,
|
||||||
peak.TimeSeconds,
|
peak.TimeSeconds - slidingStartTime,
|
||||||
peak.HorizontalFrictionN,
|
peak.HorizontalFrictionN,
|
||||||
peak.VerticalLoadN,
|
peak.VerticalLoadN,
|
||||||
staticCoefficientValue,
|
staticCoefficientValue,
|
||||||
@@ -855,16 +910,125 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
ResultSummary = $"近 3 次平均 静 {staticAverage:F2} / 动 {dynamicAverage:F2}";
|
ResultSummary = $"近 3 次平均 静 {staticAverage:F2} / 动 {dynamicAverage:F2}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SlipDataPoint FindStaticPeak(IReadOnlyList<SlipDataPoint> points)
|
private void TryMarkSlidingStart(SlipDataPoint point)
|
||||||
{
|
{
|
||||||
var preDynamicWindow = points
|
if (slidingStartTimeSeconds.HasValue)
|
||||||
.Where(point => point.TimeSeconds <= DynamicWindowStartSeconds)
|
{
|
||||||
.ToList();
|
return;
|
||||||
return (preDynamicWindow.Count > 0 ? preDynamicWindow : points)
|
|
||||||
.MaxBy(point => point.HorizontalFrictionN)
|
|
||||||
?? points[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var minimumAnalysisLoad = GetMinimumAnalysisLoad();
|
||||||
|
if (!IsSlidingStartPoint(point, runStartDisplacementMm, minimumAnalysisLoad))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
slidingStartTimeSeconds = point.TimeSeconds;
|
||||||
|
Log.Information(
|
||||||
|
"检测到有效滑动开始:TestNumber={TestNumber}, SlidingStartTime={SlidingStartTime:F3}s, StartDisplacement={StartDisplacement:F3}mm, CurrentDisplacement={CurrentDisplacement:F3}mm, DisplacementDelta={DisplacementDelta:F3}mm, VerticalLoad={VerticalLoad:F3}N, MinimumAnalysisLoad={MinimumAnalysisLoad:F3}N",
|
||||||
|
TestNumber,
|
||||||
|
point.TimeSeconds,
|
||||||
|
runStartDisplacementMm,
|
||||||
|
point.DisplacementMm,
|
||||||
|
Math.Abs(point.DisplacementMm - runStartDisplacementMm),
|
||||||
|
point.VerticalLoadN,
|
||||||
|
minimumAnalysisLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double GetMinimumAnalysisLoad() =>
|
||||||
|
TryParseLoadValue(TargetLoadText, out var targetLoad)
|
||||||
|
? Math.Max(1, targetLoad * MinimumAnalysisLoadRatio)
|
||||||
|
: 1;
|
||||||
|
|
||||||
|
private static bool TryParseLoadValue(string value, out double load)
|
||||||
|
{
|
||||||
|
var numeric = new string(value
|
||||||
|
.Where(character => char.IsDigit(character) || character is '.' or '-' or '+')
|
||||||
|
.ToArray());
|
||||||
|
return double.TryParse(numeric, NumberStyles.Float, CultureInfo.InvariantCulture, out load);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryFindSlidingStart(
|
||||||
|
IReadOnlyList<SlipDataPoint> points,
|
||||||
|
double startDisplacementMm,
|
||||||
|
double minimumAnalysisLoad,
|
||||||
|
out SlipDataPoint slidingStartPoint)
|
||||||
|
{
|
||||||
|
foreach (var point in points)
|
||||||
|
{
|
||||||
|
if (IsSlidingStartPoint(point, startDisplacementMm, minimumAnalysisLoad))
|
||||||
|
{
|
||||||
|
slidingStartPoint = point;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slidingStartPoint = points[0];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSlidingStartPoint(SlipDataPoint point, double startDisplacementMm, double minimumAnalysisLoad) =>
|
||||||
|
point.VerticalLoadN >= minimumAnalysisLoad
|
||||||
|
&& Math.Abs(point.DisplacementMm - startDisplacementMm) >= SlidingStartDisplacementThresholdMm;
|
||||||
|
|
||||||
|
private static StaticPeakSelection FindStaticPeak(IReadOnlyList<SlipDataPoint> points, double slidingStartTime)
|
||||||
|
{
|
||||||
|
var searchWindow = points
|
||||||
|
.Where(point => point.TimeSeconds >= slidingStartTime
|
||||||
|
&& point.TimeSeconds <= slidingStartTime + StaticPeakSearchEndSeconds)
|
||||||
|
.ToList();
|
||||||
|
if (searchWindow.Count == 0)
|
||||||
|
{
|
||||||
|
return new StaticPeakSelection(points[0], "NoStaticWindowFallback");
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstFriction = searchWindow[0].HorizontalFrictionN;
|
||||||
|
var peakIndex = 0;
|
||||||
|
for (var index = 1; index < searchWindow.Count; index++)
|
||||||
|
{
|
||||||
|
if (searchWindow[index].HorizontalFrictionN > searchWindow[peakIndex].HorizontalFrictionN)
|
||||||
|
{
|
||||||
|
peakIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
var peak = searchWindow[peakIndex];
|
||||||
|
var hasMeaningfulRise = peak.HorizontalFrictionN - firstFriction >= StaticPeakMinimumRiseN;
|
||||||
|
if (!hasMeaningfulRise)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var confirmationEnd = Math.Min(
|
||||||
|
searchWindow.Count - 1,
|
||||||
|
index + StaticPeakDropConfirmationPointCount - 1);
|
||||||
|
if (confirmationEnd - index + 1 < StaticPeakDropConfirmationPointCount)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isConfirmedFalling = true;
|
||||||
|
for (var confirmationIndex = index; confirmationIndex <= confirmationEnd; confirmationIndex++)
|
||||||
|
{
|
||||||
|
if (searchWindow[confirmationIndex].HorizontalFrictionN > peak.HorizontalFrictionN - StaticPeakDropToleranceN)
|
||||||
|
{
|
||||||
|
isConfirmedFalling = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isConfirmedFalling)
|
||||||
|
{
|
||||||
|
return new StaticPeakSelection(peak, "FirstConfirmedPeak");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StaticPeakSelection(
|
||||||
|
searchWindow.MaxBy(point => point.HorizontalFrictionN) ?? searchWindow[0],
|
||||||
|
"MaxFallback");
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed record StaticPeakSelection(SlipDataPoint Point, string Mode);
|
||||||
|
|
||||||
private static double CalculateCoefficient(double frictionForce, double verticalLoad) =>
|
private static double CalculateCoefficient(double frictionForce, double verticalLoad) =>
|
||||||
Math.Abs(verticalLoad) > 0.0001 ? frictionForce / verticalLoad : 0;
|
Math.Abs(verticalLoad) > 0.0001 ? frictionForce / verticalLoad : 0;
|
||||||
|
|
||||||
@@ -942,15 +1106,16 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
|
|
||||||
lastRealtimeCurveTraceLoggedAt = now;
|
lastRealtimeCurveTraceLoggedAt = now;
|
||||||
Log.Debug(
|
Log.Debug(
|
||||||
"实时曲线点同步:TestNumber={TestNumber}, PointIndex={PointIndex}, Time={Time:F3}s, Vertical={Vertical:F3}N, Friction={Friction:F3}N, Coefficient={Coefficient:F5}, Displacement={Displacement:F3}mm, InDynamicWindow={InDynamicWindow}, ChartCount={ChartCount}",
|
"实时曲线点同步:TestNumber={TestNumber}, PointIndex={PointIndex}, Time={Time:F3}s, StandardTime={StandardTime}, Vertical={Vertical:F3}N, Friction={Friction:F3}N, Coefficient={Coefficient:F5}, Displacement={Displacement:F3}mm, InDynamicWindow={InDynamicWindow}, ChartCount={ChartCount}",
|
||||||
TestNumber,
|
TestNumber,
|
||||||
expectedCount,
|
expectedCount,
|
||||||
point.TimeSeconds,
|
point.TimeSeconds,
|
||||||
|
FormatRelativeTime(point, slidingStartTimeSeconds),
|
||||||
point.VerticalLoadN,
|
point.VerticalLoadN,
|
||||||
point.HorizontalFrictionN,
|
point.HorizontalFrictionN,
|
||||||
point.FrictionCoefficient,
|
point.FrictionCoefficient,
|
||||||
point.DisplacementMm,
|
point.DisplacementMm,
|
||||||
point.TimeSeconds >= DynamicWindowStartSeconds && point.TimeSeconds <= DynamicWindowEndSeconds,
|
IsInDynamicWindow(point, slidingStartTimeSeconds),
|
||||||
expectedCount);
|
expectedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,6 +1133,22 @@ namespace Footwear_Test_methodsfor_wholeshoe_Slipresistanceperformance.ViewModel
|
|||||||
private static string FormatNullable(double? value) =>
|
private static string FormatNullable(double? value) =>
|
||||||
value.HasValue ? value.Value.ToString("F3", CultureInfo.InvariantCulture) : "null";
|
value.HasValue ? value.Value.ToString("F3", CultureInfo.InvariantCulture) : "null";
|
||||||
|
|
||||||
|
private static string FormatRelativeTime(SlipDataPoint? point, double? startTime) =>
|
||||||
|
point is null || !startTime.HasValue
|
||||||
|
? "null"
|
||||||
|
: (point.TimeSeconds - startTime.Value).ToString("F3", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
private static bool IsInDynamicWindow(SlipDataPoint point, double? startTime)
|
||||||
|
{
|
||||||
|
if (!startTime.HasValue)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var standardTime = point.TimeSeconds - startTime.Value;
|
||||||
|
return standardTime >= DynamicWindowStartSeconds && standardTime <= DynamicWindowEndSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
private static string FormatDataPoint(SlipDataPoint? point) =>
|
private static string FormatDataPoint(SlipDataPoint? point) =>
|
||||||
point is null
|
point is null
|
||||||
? "null"
|
? "null"
|
||||||
|
|||||||
Reference in New Issue
Block a user