更新2026

This commit is contained in:
GukSang.Jin
2026-05-30 15:04:42 +08:00
parent c2c5ad73a8
commit 0a908d85df
6 changed files with 341 additions and 110 deletions

View File

@@ -42,7 +42,7 @@ public sealed record MethodAResult(
double ThermalCoefficientOfVariation,
bool PassedDeviationCheck);
public sealed record MethodBMoistureResult(
public sealed record MethodBMoistureTrialResult(
double M1,
double M2,
double M3,
@@ -61,10 +61,22 @@ public sealed record MethodBMoistureResult(
double XT180Corrected,
bool IsValid);
public sealed record MethodBWarmthResult(
public sealed record MethodBMoistureResult(
MethodBMoistureTrialResult Trial1,
MethodBMoistureTrialResult Trial2,
double AverageT180Corrected,
double AverageXT180Corrected,
bool IsValid);
public sealed record MethodBWarmthCycleResult(
double EnergyKilojoules,
double Seconds,
double HeatWatts,
double FootTemperatureC,
double ChamberTemperatureC,
double ThermalResistance);
public sealed record MethodBWarmthResult(
MethodBWarmthCycleResult Cycle1,
MethodBWarmthCycleResult Cycle2,
double AverageThermalResistance);

View File

@@ -63,7 +63,11 @@ public sealed class ExcelReportService
else if (record.Method.StartsWith("方法 B", StringComparison.Ordinal))
{
sheets.Add(CreateMethodBResultSheet(root, record.Method));
sheets.Add(CreateMethodBMassSheet(root));
if (record.Method.Contains("吸湿透水汽", StringComparison.Ordinal))
{
sheets.Add(CreateMethodBMassSheet(root));
}
sheets.Add(CreateProcedureSheet(root));
}
@@ -111,12 +115,12 @@ public sealed class ExcelReportService
rows.Add(Row("方法 B 试样", "满帮鞋同号两只;试验前在 (23±2) ℃、(50±5)% RH 标准环境调节", record.SampleDescription));
rows.Add(Row("方法 B 供水", "泵流量 (5.0±0.3) cm3/h测试周期 (180±1) min", record.Conditions));
rows.Add(Row("方法 B 称重", "m11-m72 均精确到 0.01 gm180 应在 (15±0.9) g 范围内", record.IsValid ? "m180 有效" : "m180 超限"));
rows.Add(Row("方法 B 结果", "透水汽性能 T180*吸湿透水汽性能 XT180*=T180*+m3*+m4*,保留两位小数", record.ResultSummary));
rows.Add(Row("方法 B 结果", "两次试验结果取平均;透水汽性能 T180*吸湿透水汽性能 XT180*=T180*+m3*+m4*最终保留两位小数", record.ResultSummary));
}
else
{
rows.Add(Row("方法 B 保暖", "假脚温度 (38±1) ℃;测试周期 (180±1) min连续测试 2 个周期", record.Conditions));
rows.Add(Row("方法 B 热阻", "Q=P/t×1000R=S×(Tf-Tc)/Q,结果保留三位小数", record.ResultSummary));
rows.Add(Row("方法 B 热阻", "每个周期 Q=P/t×1000R=S×(Tf-Tc)/Q;最终取两次热阻平均值并保留三位小数", record.ResultSummary));
}
return new WorksheetData("标准核对", rows);
@@ -156,8 +160,8 @@ public sealed class ExcelReportService
{
var waterLoss = GetDouble(sample, "WaterLossGramsPerHour");
var power = GetDouble(sample, "PowerWatts");
var moistureHeat = sample.TryGetProperty("MoistureHeatWatts", out _) ? GetDouble(sample, "MoistureHeatWatts") : Math.Round(0.672 * Math.Max(waterLoss, 0.001), 3);
var dryHeat = sample.TryGetProperty("DryHeatWatts", out _) ? GetDouble(sample, "DryHeatWatts") : Math.Round(Math.Max(power - moistureHeat, 0.001), 3);
var moistureHeat = sample.TryGetProperty("MoistureHeatWatts", out _) ? GetDouble(sample, "MoistureHeatWatts") : (waterLoss > 0 ? Round(0.672 * waterLoss, 3) : 0);
var dryHeat = sample.TryGetProperty("DryHeatWatts", out _) ? GetDouble(sample, "DryHeatWatts") : (power > moistureHeat ? Round(power - moistureHeat, 3) : 0);
rows.Add(Row(
GetDouble(sample, "Index"),
GetString(sample, "Timestamp"),
@@ -186,37 +190,67 @@ public sealed class ExcelReportService
if (method.Contains("吸湿透水汽", StringComparison.Ordinal))
{
rows.Add(Row("m5", GetDouble(result, "M5"), "gC1 消耗水量"));
rows.Add(Row("m6", GetDouble(result, "M6"), "gC2 蒸发水量"));
rows.Add(Row("m7", GetDouble(result, "M7"), "gC3 蒸发水量"));
rows.Add(Row("m8", GetDouble(result, "M8"), "gC2/C3 平均蒸发量"));
rows.Add(Row("m180", GetDouble(result, "M180"), "g泵进鞋腔内水总质量15±0.9 g"));
rows.Add(Row("m1", GetDouble(result, "M1"), "g模拟皮肤质量变化"));
rows.Add(Row("m2", GetDouble(result, "M2"), "g标准长筒袜质量变化"));
rows.Add(Row("m3", GetDouble(result, "M3"), "g样品鞋质量变化"));
rows.Add(Row("m4", GetDouble(result, "M4"), "g鞋垫质量变化"));
rows.Add(Row("T180", GetDouble(result, "T180"), "g散发到环境中的水汽质量"));
rows.Add(Row("m1*", GetDouble(result, "M1Corrected"), "g按 15 g 修正"));
rows.Add(Row("m2*", GetDouble(result, "M2Corrected"), "g按 15 g 修正"));
rows.Add(Row("m3*", GetDouble(result, "M3Corrected"), "g按 15 g 修正"));
rows.Add(Row("m4*", GetDouble(result, "M4Corrected"), "g按 15 g 修正"));
rows.Add(Row("T180*", GetDouble(result, "T180Corrected"), "g透水汽性能"));
rows.Add(Row("XT180*", GetDouble(result, "XT180Corrected"), "g吸湿透水汽性能"));
rows.Add(Row("有效性", GetBool(result, "IsValid") ? "有效" : "m180 超出 15±0.9 g", ""));
if (result.TryGetProperty("Trial1", out var trial1) && result.TryGetProperty("Trial2", out var trial2))
{
rows.Add(Row("T180* 平均值", GetDouble(result, "AverageT180Corrected"), "g透水汽性能最终保留两位小数"));
rows.Add(Row("XT180* 平均值", GetDouble(result, "AverageXT180Corrected"), "g吸湿透水汽性能最终保留两位小数"));
rows.Add(Row("有效性", GetBool(result, "IsValid") ? "有效" : "至少一次 m180 超出 15±0.9 g", ""));
AddMoistureTrialRows(rows, "第1次", trial1);
AddMoistureTrialRows(rows, "第2次", trial2);
}
else
{
AddMoistureTrialRows(rows, "单次", result);
rows.Add(Row("有效性", GetBool(result, "IsValid") ? "有效" : "m180 超出 15±0.9 g", ""));
}
}
else
{
rows.Add(Row("P", GetDouble(result, "EnergyKilojoules"), "kJ180 min 能量消耗"));
rows.Add(Row("t", GetDouble(result, "Seconds"), "s测试周期"));
rows.Add(Row("Q", GetDouble(result, "HeatWatts"), "W单位时间热量消耗"));
rows.Add(Row("Tf", GetDouble(result, "FootTemperatureC"), "℃,假脚表面温度平均值"));
rows.Add(Row("Tc", GetDouble(result, "ChamberTemperatureC"), "℃,测试箱环境温度平均值"));
rows.Add(Row("R", GetDouble(result, "ThermalResistance"), "m2·℃/W保暖性能热阻值"));
if (result.TryGetProperty("Cycle1", out var cycle1) && result.TryGetProperty("Cycle2", out var cycle2))
{
rows.Add(Row("R 平均值", GetDouble(result, "AverageThermalResistance"), "m2·℃/W最终保留三位小数"));
AddWarmthCycleRows(rows, "第1周期", cycle1);
AddWarmthCycleRows(rows, "第2周期", cycle2);
}
else
{
AddWarmthCycleRows(rows, "单周期", result);
}
}
return new WorksheetData("方法B结果", rows);
}
private static void AddMoistureTrialRows(List<IReadOnlyList<object?>> rows, string prefix, JsonElement trial)
{
rows.Add(Row($"{prefix} m5", GetDouble(trial, "M5"), "gC1 消耗水量"));
rows.Add(Row($"{prefix} m6", GetDouble(trial, "M6"), "gC2 蒸发水量"));
rows.Add(Row($"{prefix} m7", GetDouble(trial, "M7"), "gC3 蒸发水量"));
rows.Add(Row($"{prefix} m8", GetDouble(trial, "M8"), "gC2/C3 平均蒸发量"));
rows.Add(Row($"{prefix} m180", GetDouble(trial, "M180"), "g泵进鞋腔内水总质量15±0.9 g"));
rows.Add(Row($"{prefix} m1", GetDouble(trial, "M1"), "g模拟皮肤质量变化"));
rows.Add(Row($"{prefix} m2", GetDouble(trial, "M2"), "g标准长筒袜质量变化"));
rows.Add(Row($"{prefix} m3", GetDouble(trial, "M3"), "g样品鞋质量变化"));
rows.Add(Row($"{prefix} m4", GetDouble(trial, "M4"), "g鞋垫质量变化"));
rows.Add(Row($"{prefix} T180", GetDouble(trial, "T180"), "g散发到环境中的水汽质量"));
rows.Add(Row($"{prefix} m1*", GetDouble(trial, "M1Corrected"), "g按 15 g 修正"));
rows.Add(Row($"{prefix} m2*", GetDouble(trial, "M2Corrected"), "g按 15 g 修正"));
rows.Add(Row($"{prefix} m3*", GetDouble(trial, "M3Corrected"), "g按 15 g 修正"));
rows.Add(Row($"{prefix} m4*", GetDouble(trial, "M4Corrected"), "g按 15 g 修正"));
rows.Add(Row($"{prefix} T180*", GetDouble(trial, "T180Corrected"), "g透水汽性能"));
rows.Add(Row($"{prefix} XT180*", GetDouble(trial, "XT180Corrected"), "g吸湿透水汽性能"));
}
private static void AddWarmthCycleRows(List<IReadOnlyList<object?>> rows, string prefix, JsonElement cycle)
{
rows.Add(Row($"{prefix} P", GetDouble(cycle, "EnergyKilojoules"), "kJ180 min 能量消耗"));
rows.Add(Row($"{prefix} t", GetDouble(cycle, "Seconds"), "s测试周期"));
rows.Add(Row($"{prefix} Q", GetDouble(cycle, "HeatWatts"), "W单位时间热量消耗"));
rows.Add(Row($"{prefix} Tf", GetDouble(cycle, "FootTemperatureC"), "℃,假脚表面温度平均值"));
rows.Add(Row($"{prefix} Tc", GetDouble(cycle, "ChamberTemperatureC"), "℃,测试箱环境温度平均值"));
rows.Add(Row($"{prefix} R", GetDouble(cycle, "ThermalResistance"), "m2·℃/W保暖性能热阻值"));
}
private static WorksheetData CreateMethodBMassSheet(JsonElement root)
{
var rows = new List<IReadOnlyList<object?>>
@@ -226,25 +260,39 @@ public sealed class ExcelReportService
if (root.TryGetProperty("Masses", out var masses))
{
rows.Add(Row("m11", GetDouble(masses, "M11"), "模拟皮肤测试前质量"));
rows.Add(Row("m12", GetDouble(masses, "M12"), "模拟皮肤测试后质量"));
rows.Add(Row("m21", GetDouble(masses, "M21"), "标准长筒袜测试前质量"));
rows.Add(Row("m22", GetDouble(masses, "M22"), "标准长筒袜测试后质量"));
rows.Add(Row("m31", GetDouble(masses, "M31"), "样品鞋测试前质量"));
rows.Add(Row("m32", GetDouble(masses, "M32"), "样品鞋测试后质量"));
rows.Add(Row("m41", GetDouble(masses, "M41"), "鞋垫测试前质量"));
rows.Add(Row("m42", GetDouble(masses, "M42"), "鞋垫测试后质量"));
rows.Add(Row("m51", GetDouble(masses, "M51"), "C1 测试前质量"));
rows.Add(Row("m52", GetDouble(masses, "M52"), "C1 测试后质量"));
rows.Add(Row("m61", GetDouble(masses, "M61"), "C2 测试前质量"));
rows.Add(Row("m62", GetDouble(masses, "M62"), "C2 测试后质量"));
rows.Add(Row("m71", GetDouble(masses, "M71"), "C3 测试前质量"));
rows.Add(Row("m72", GetDouble(masses, "M72"), "C3 测试后质量"));
if (masses.TryGetProperty("Trial1", out var trial1) && masses.TryGetProperty("Trial2", out var trial2))
{
AddMassRows(rows, "第1次", trial1);
AddMassRows(rows, "第2次", trial2);
}
else
{
AddMassRows(rows, "", masses);
}
}
return new WorksheetData("方法B称重", rows);
}
private static void AddMassRows(List<IReadOnlyList<object?>> rows, string prefix, JsonElement masses)
{
var label = string.IsNullOrWhiteSpace(prefix) ? "" : $"{prefix} ";
rows.Add(Row($"{label}m11", GetDouble(masses, "M11"), "模拟皮肤测试前质量"));
rows.Add(Row($"{label}m12", GetDouble(masses, "M12"), "模拟皮肤测试后质量"));
rows.Add(Row($"{label}m21", GetDouble(masses, "M21"), "标准长筒袜测试前质量"));
rows.Add(Row($"{label}m22", GetDouble(masses, "M22"), "标准长筒袜测试后质量"));
rows.Add(Row($"{label}m31", GetDouble(masses, "M31"), "样品鞋测试前质量"));
rows.Add(Row($"{label}m32", GetDouble(masses, "M32"), "样品鞋测试后质量"));
rows.Add(Row($"{label}m41", GetDouble(masses, "M41"), "鞋垫测试前质量"));
rows.Add(Row($"{label}m42", GetDouble(masses, "M42"), "鞋垫测试后质量"));
rows.Add(Row($"{label}m51", GetDouble(masses, "M51"), "C1 测试前质量"));
rows.Add(Row($"{label}m52", GetDouble(masses, "M52"), "C1 测试后质量"));
rows.Add(Row($"{label}m61", GetDouble(masses, "M61"), "C2 测试前质量"));
rows.Add(Row($"{label}m62", GetDouble(masses, "M62"), "C2 测试后质量"));
rows.Add(Row($"{label}m71", GetDouble(masses, "M71"), "C3 测试前质量"));
rows.Add(Row($"{label}m72", GetDouble(masses, "M72"), "C3 测试后质量"));
}
private static WorksheetData CreateProcedureSheet(JsonElement root)
{
var rows = new List<IReadOnlyList<object?>>
@@ -471,6 +519,11 @@ public sealed class ExcelReportService
return element.TryGetProperty(property, out var value) && value.ValueKind == JsonValueKind.True;
}
private static double Round(double value, int digits)
{
return Math.Round(value, digits, MidpointRounding.AwayFromZero);
}
private static string ColumnName(int column)
{
var name = "";

View File

@@ -8,6 +8,8 @@ namespace FootwearTest.Services;
public sealed class TestFormulaService
{
private const double VaporizationHeatWhPerGram = 0.672;
private const double MethodBTargetWaterGrams = 15.0;
private const double MethodBWaterToleranceGrams = 0.9;
public double CalculateSkinMoistureResistance(
double footAreaSquareMeters,
@@ -17,9 +19,11 @@ public sealed class TestFormulaService
double environmentRelativeHumidity,
double nakedFootSweatGramsPerHour)
{
EnsurePositive(nakedFootSweatGramsPerHour, "裸脚状态下的出汗量 Qn");
return footAreaSquareMeters *
(skinSaturatedVaporPressurePa * skinRelativeHumidity - environmentSaturatedVaporPressurePa * environmentRelativeHumidity) /
(VaporizationHeatWhPerGram * Math.Max(nakedFootSweatGramsPerHour, 0.001));
(VaporizationHeatWhPerGram * nakedFootSweatGramsPerHour);
}
public MethodASampleRecord CalculateMethodASample(
@@ -30,11 +34,15 @@ public sealed class TestFormulaService
double skinSaturatedVaporPressurePa = 5623.0,
double environmentSaturatedVaporPressurePa = 2809.0)
{
var he = VaporizationHeatWhPerGram * Math.Max(snapshot.WaterLossGramsPerHour, 0.001);
EnsurePositive(snapshot.WaterLossGramsPerHour, "整鞋蒸发出汗量 Q");
var he = VaporizationHeatWhPerGram * snapshot.WaterLossGramsPerHour;
var re = footAreaSquareMeters *
(skinSaturatedVaporPressurePa - environmentSaturatedVaporPressurePa * snapshot.EnvironmentHumidityPercent / 100.0) /
he - skinMoistureResistance;
var hd = Math.Max(snapshot.PowerWatts - he, 0.001);
var hd = snapshot.PowerWatts - he;
EnsurePositive(hd, "通过整鞋的干热量 Hd");
var rt = footAreaSquareMeters * (snapshot.FootTemperatureC - snapshot.EnvironmentTemperatureC) / hd;
return new MethodASampleRecord(
@@ -45,10 +53,10 @@ public sealed class TestFormulaService
snapshot.EnvironmentHumidityPercent,
snapshot.WaterLossGramsPerHour,
snapshot.PowerWatts,
Math.Round(he, 3),
Math.Round(hd, 3),
Math.Round(re, 3),
Math.Round(rt, 4));
Round(he, 3),
Round(hd, 3),
Round(re, 3),
Round(rt, 4));
}
public double Average(IEnumerable<double> values)
@@ -87,7 +95,7 @@ public sealed class TestFormulaService
return list.All(value => Math.Abs(value - average) <= Math.Abs(average) * 0.10);
}
public MethodBMoistureResult CalculateMethodBMoisture(
public MethodBMoistureTrialResult CalculateMethodBMoistureTrial(
double m11,
double m12,
double m21,
@@ -108,49 +116,92 @@ public sealed class TestFormulaService
var m7 = m71 - m72;
var m8 = (m6 + m7) / 2.0;
var m180 = m5 - m8;
var scale = 15.0 / Math.Max(m180, 0.001);
EnsurePositive(m180, "180 min 测试过程中泵进鞋腔内水的总质量 m180");
var scale = MethodBTargetWaterGrams / m180;
var m1 = m12 - m11;
var m2 = m22 - m21;
var m3 = m32 - m31;
var m4 = m42 - m41;
var t180 = m180 - m1 - m2 - m3 - m4;
var t180Corrected = t180 * scale;
var m3Corrected = m3 * scale;
var m4Corrected = m4 * scale;
return new MethodBMoistureResult(
Math.Round(m1, 3),
Math.Round(m2, 3),
Math.Round(m3, 3),
Math.Round(m4, 3),
Math.Round(m5, 3),
Math.Round(m6, 3),
Math.Round(m7, 3),
Math.Round(m8, 3),
Math.Round(m180, 3),
Math.Round(t180, 3),
Math.Round(m1 * scale, 3),
Math.Round(m2 * scale, 3),
Math.Round(m3 * scale, 3),
Math.Round(m4 * scale, 3),
Math.Round(t180 * scale, 3),
Math.Round((t180 + m3 + m4) * scale, 3),
m180 >= 14.1 && m180 <= 15.9);
return new MethodBMoistureTrialResult(
Round(m1, 3),
Round(m2, 3),
Round(m3, 3),
Round(m4, 3),
Round(m5, 3),
Round(m6, 3),
Round(m7, 3),
Round(m8, 3),
Round(m180, 3),
Round(t180, 3),
Round(m1 * scale, 3),
Round(m2 * scale, 3),
Round(m3Corrected, 3),
Round(m4Corrected, 3),
Round(t180Corrected, 3),
Round(t180Corrected + m3Corrected + m4Corrected, 3),
m180 >= MethodBTargetWaterGrams - MethodBWaterToleranceGrams &&
m180 <= MethodBTargetWaterGrams + MethodBWaterToleranceGrams);
}
public MethodBWarmthResult CalculateMethodBWarmth(
public MethodBMoistureResult CalculateMethodBMoisture(
MethodBMoistureTrialResult trial1,
MethodBMoistureTrialResult trial2)
{
return new MethodBMoistureResult(
trial1,
trial2,
Round((trial1.T180Corrected + trial2.T180Corrected) / 2.0, 2),
Round((trial1.XT180Corrected + trial2.XT180Corrected) / 2.0, 2),
trial1.IsValid && trial2.IsValid);
}
public MethodBWarmthCycleResult CalculateMethodBWarmthCycle(
double energyKilojoules,
double seconds,
double footAreaSquareMeters,
double footTemperatureC,
double chamberTemperatureC)
{
var heatWatts = energyKilojoules / Math.Max(seconds, 1.0) * 1000.0;
var resistance = footAreaSquareMeters * (footTemperatureC - chamberTemperatureC) / Math.Max(heatWatts, 0.001);
return new MethodBWarmthResult(
Math.Round(energyKilojoules, 1),
EnsurePositive(seconds, "测试周期时长 t");
EnsurePositive(energyKilojoules, "180 min 测试周期内的能量消耗 P");
var heatWatts = energyKilojoules / seconds * 1000.0;
var resistance = footAreaSquareMeters * (footTemperatureC - chamberTemperatureC) / heatWatts;
return new MethodBWarmthCycleResult(
Round(energyKilojoules, 1),
seconds,
Math.Round(heatWatts, 3),
Math.Round(footTemperatureC, 2),
Math.Round(chamberTemperatureC, 2),
Math.Round(resistance, 3));
Round(heatWatts, 3),
Round(footTemperatureC, 2),
Round(chamberTemperatureC, 2),
Round(resistance, 3));
}
public MethodBWarmthResult CalculateMethodBWarmth(
MethodBWarmthCycleResult cycle1,
MethodBWarmthCycleResult cycle2)
{
return new MethodBWarmthResult(
cycle1,
cycle2,
Round((cycle1.ThermalResistance + cycle2.ThermalResistance) / 2.0, 3));
}
private static double Round(double value, int digits)
{
return Math.Round(value, digits, MidpointRounding.AwayFromZero);
}
private static void EnsurePositive(double value, string name)
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException(nameof(value), value, $"{name} 必须大于 0无法按 GB/T 33393 公式计算。");
}
}
}

View File

@@ -120,6 +120,7 @@ public partial class MethodAViewModel : ViewModelBase
Samples.Clear();
await _deviceClient.SetOutputsAsync(true, true, true);
var skinResistanceValues = new double[30];
for (var i = 1; i <= 30; i++)
{
await Task.Delay(60);
@@ -131,12 +132,16 @@ public partial class MethodAViewModel : ViewModelBase
2809.0,
snapshot.EnvironmentHumidityPercent / 100.0,
snapshot.WaterLossGramsPerHour);
SkinMoistureResistance = Math.Round(value, 3);
Samples.Add(_formulaService.CalculateMethodASample(i, snapshot, _settings.FootAreaSquareMeters, SkinMoistureResistance));
skinResistanceValues[i - 1] = value;
SkinMoistureResistance = Round(_formulaService.Average(skinResistanceValues.Take(i)), 3);
}
await _deviceClient.SetOutputsAsync(false, true, false);
UpdateMethodAResult("皮肤湿阻");
MoistureCvPercent = Round(_formulaService.CoefficientOfVariationPercent(skinResistanceValues), 2);
ThermalCvPercent = 0;
AverageMoistureResistance = 0;
AverageThermalResistance = 0;
ResultText = $"皮肤湿阻: Res {SkinMoistureResistance:F3} Pa·m²/WCV {MoistureCvPercent:F2}%";
var id = await SaveRunAsync("方法 A - 皮肤湿阻", true);
StatusText = "皮肤湿阻测定完成";
_logger.LogInformation("Method A skin moisture resistance completed. RecordId={RecordId}, Samples={Samples}, Result={ResultText}", id, Samples.Count, ResultText);
@@ -178,7 +183,9 @@ public partial class MethodAViewModel : ViewModelBase
}
await _deviceClient.SetOutputsAsync(false, true, false);
var passed = _formulaService.PassesTenPercentDeviation(Samples.Select(sample => sample.ThermalResistance));
var passed =
_formulaService.PassesTenPercentDeviation(Samples.Select(sample => sample.MoistureResistance)) &&
_formulaService.PassesTenPercentDeviation(Samples.Select(sample => sample.ThermalResistance));
UpdateMethodAResult("整鞋热阻/湿阻");
var id = await SaveRunAsync("方法 A - 整鞋热阻/湿阻", passed);
StatusText = passed ? "试验完成" : "结果偏差超过 ±10%,建议重测";
@@ -222,13 +229,18 @@ public partial class MethodAViewModel : ViewModelBase
private void UpdateMethodAResult(string stage)
{
AverageMoistureResistance = Math.Round(_formulaService.Average(Samples.Select(sample => sample.MoistureResistance)), 3);
AverageThermalResistance = Math.Round(_formulaService.Average(Samples.Select(sample => sample.ThermalResistance)), 4);
MoistureCvPercent = Math.Round(_formulaService.CoefficientOfVariationPercent(Samples.Select(sample => sample.MoistureResistance)), 2);
ThermalCvPercent = Math.Round(_formulaService.CoefficientOfVariationPercent(Samples.Select(sample => sample.ThermalResistance)), 2);
AverageMoistureResistance = Round(_formulaService.Average(Samples.Select(sample => sample.MoistureResistance)), 3);
AverageThermalResistance = Round(_formulaService.Average(Samples.Select(sample => sample.ThermalResistance)), 4);
MoistureCvPercent = Round(_formulaService.CoefficientOfVariationPercent(Samples.Select(sample => sample.MoistureResistance)), 2);
ThermalCvPercent = Round(_formulaService.CoefficientOfVariationPercent(Samples.Select(sample => sample.ThermalResistance)), 2);
ResultText = $"{stage}: 湿阻 {AverageMoistureResistance:F3} Pa·m²/W热阻 {AverageThermalResistance:F4} m²·℃/WCV {ThermalCvPercent:F2}%";
}
private static double Round(double value, int digits)
{
return Math.Round(value, digits, MidpointRounding.AwayFromZero);
}
private async Task StopOutputsAfterFailureAsync(string reason)
{
try

View File

@@ -57,8 +57,24 @@ public partial class MethodBViewModel : ViewModelBase
private double _m62 = 99.80;
private double _m71 = 100.00;
private double _m72 = 99.78;
private double _m11Second = 6.00;
private double _m12Second = 7.08;
private double _m21Second = 14.00;
private double _m22Second = 16.36;
private double _m31Second = 410.00;
private double _m32Second = 413.15;
private double _m41Second = 18.00;
private double _m42Second = 18.95;
private double _m51Second = 100.00;
private double _m52Second = 84.74;
private double _m61Second = 100.00;
private double _m62Second = 99.81;
private double _m71Second = 100.00;
private double _m72Second = 99.79;
private double _warmthEnergyKilojoules = 48.2;
private double _warmthSeconds = 10800;
private double _warmthEnergyKilojoulesSecond = 48.0;
private double _warmthSecondsSecond = 10800;
public string SampleDescription { get => _sampleDescription; set => SetProperty(ref _sampleDescription, value); }
public string StatusText { get => _statusText; set => SetProperty(ref _statusText, value); }
@@ -80,8 +96,24 @@ public partial class MethodBViewModel : ViewModelBase
public double M62 { get => _m62; set => SetProperty(ref _m62, value); }
public double M71 { get => _m71; set => SetProperty(ref _m71, value); }
public double M72 { get => _m72; set => SetProperty(ref _m72, value); }
public double M11Second { get => _m11Second; set => SetProperty(ref _m11Second, value); }
public double M12Second { get => _m12Second; set => SetProperty(ref _m12Second, value); }
public double M21Second { get => _m21Second; set => SetProperty(ref _m21Second, value); }
public double M22Second { get => _m22Second; set => SetProperty(ref _m22Second, value); }
public double M31Second { get => _m31Second; set => SetProperty(ref _m31Second, value); }
public double M32Second { get => _m32Second; set => SetProperty(ref _m32Second, value); }
public double M41Second { get => _m41Second; set => SetProperty(ref _m41Second, value); }
public double M42Second { get => _m42Second; set => SetProperty(ref _m42Second, value); }
public double M51Second { get => _m51Second; set => SetProperty(ref _m51Second, value); }
public double M52Second { get => _m52Second; set => SetProperty(ref _m52Second, value); }
public double M61Second { get => _m61Second; set => SetProperty(ref _m61Second, value); }
public double M62Second { get => _m62Second; set => SetProperty(ref _m62Second, value); }
public double M71Second { get => _m71Second; set => SetProperty(ref _m71Second, value); }
public double M72Second { get => _m72Second; set => SetProperty(ref _m72Second, value); }
public double WarmthEnergyKilojoules { get => _warmthEnergyKilojoules; set => SetProperty(ref _warmthEnergyKilojoules, value); }
public double WarmthSeconds { get => _warmthSeconds; set => SetProperty(ref _warmthSeconds, value); }
public double WarmthEnergyKilojoulesSecond { get => _warmthEnergyKilojoulesSecond; set => SetProperty(ref _warmthEnergyKilojoulesSecond, value); }
public double WarmthSecondsSecond { get => _warmthSecondsSecond; set => SetProperty(ref _warmthSecondsSecond, value); }
private async Task RunMoistureAsync()
{
@@ -101,13 +133,15 @@ public partial class MethodBViewModel : ViewModelBase
ProcedureLog.Add("模拟 180 min 周期完成,关闭泵、风扇及温控。");
await _deviceClient.SetOutputsAsync(false, false, false);
var result = _formulaService.CalculateMethodBMoisture(M11, M12, M21, M22, M31, M32, M41, M42, M51, M52, M61, M62, M71, M72);
var trial1 = _formulaService.CalculateMethodBMoistureTrial(M11, M12, M21, M22, M31, M32, M41, M42, M51, M52, M61, M62, M71, M72);
var trial2 = _formulaService.CalculateMethodBMoistureTrial(M11Second, M12Second, M21Second, M22Second, M31Second, M32Second, M41Second, M42Second, M51Second, M52Second, M61Second, M62Second, M71Second, M72Second);
var result = _formulaService.CalculateMethodBMoisture(trial1, trial2);
MoistureResultText = result.IsValid
? $"T180*={result.T180Corrected:F2} gXT180*={result.XT180Corrected:F2} gm180={result.M180:F2} g"
: $"m180={result.M180:F2} g超出 15±0.9 g结果作废";
? $"T180*平均={result.AverageT180Corrected:F2} gXT180*平均={result.AverageXT180Corrected:F2} g"
: $"第1次 m180={trial1.M180:F2} g第2次 m180={trial2.M180:F2} g存在超出 15±0.9 g结果作废";
MoistureDetailText =
$"m1={result.M1:F3} gm2={result.M2:F3} gm3={result.M3:F3} gm4={result.M4:F3} g\n" +
$"m5={result.M5:F3} gm6={result.M6:F3} gm7={result.M7:F3} gm8={result.M8:F3} gT180={result.T180:F3} g";
$"第1次: m180={trial1.M180:F3} gT180*={trial1.T180Corrected:F3} gXT180*={trial1.XT180Corrected:F3} g\n" +
$"第2次: m180={trial2.M180:F3} gT180*={trial2.T180Corrected:F3} gXT180*={trial2.XT180Corrected:F3} g";
StatusText = result.IsValid ? "吸湿透水汽测试完成" : "吸湿透水汽测试需重测";
var id = await SaveRunAsync("方法 B - 吸湿透水汽性能", MoistureResultText, result, result.IsValid);
@@ -133,17 +167,26 @@ public partial class MethodBViewModel : ViewModelBase
ProcedureLog.Add("开启风扇和温控,稳定到 38±1 ℃。");
await _deviceClient.SetOutputsAsync(false, true, true);
await Task.Delay(500);
ProcedureLog.Add("记录两个 180 min 周期能量消耗,生成热阻结果。");
ProcedureLog.Add("记录两个 180 min 周期能量消耗,分别计算热阻并取平均。");
await _deviceClient.SetOutputsAsync(false, false, false);
var result = _formulaService.CalculateMethodBWarmth(
var cycle1 = _formulaService.CalculateMethodBWarmthCycle(
WarmthEnergyKilojoules,
WarmthSeconds,
_settings.FootAreaSquareMeters,
_settings.MethodBWarmthTargetTemperatureC,
_settings.EnvironmentTemperatureC);
WarmthResultText = $"Q={result.HeatWatts:F3} WR={result.ThermalResistance:F3} m²·℃/W";
WarmthDetailText = $"P={result.EnergyKilojoules:F1} kJt={result.Seconds:F0} sTf={result.FootTemperatureC:F2} ℃Tc={result.ChamberTemperatureC:F2} ℃";
var cycle2 = _formulaService.CalculateMethodBWarmthCycle(
WarmthEnergyKilojoulesSecond,
WarmthSecondsSecond,
_settings.FootAreaSquareMeters,
_settings.MethodBWarmthTargetTemperatureC,
_settings.EnvironmentTemperatureC);
var result = _formulaService.CalculateMethodBWarmth(cycle1, cycle2);
WarmthResultText = $"R平均={result.AverageThermalResistance:F3} m²·℃/W";
WarmthDetailText =
$"第1周期: P={cycle1.EnergyKilojoules:F1} kJQ={cycle1.HeatWatts:F3} WR={cycle1.ThermalResistance:F3} m²·℃/W\n" +
$"第2周期: P={cycle2.EnergyKilojoules:F1} kJQ={cycle2.HeatWatts:F3} WR={cycle2.ThermalResistance:F3} m²·℃/W";
StatusText = "保暖性能测试完成";
var id = await SaveRunAsync("方法 B - 保暖性能", WarmthResultText, result, true);
@@ -180,12 +223,29 @@ public partial class MethodBViewModel : ViewModelBase
private async Task<long> SaveRunAsync(string method, string summary, object result, bool isValid)
{
var data = JsonSerializer.Serialize(new
{
Result = result,
Masses = new { M11, M12, M21, M22, M31, M32, M41, M42, M51, M52, M61, M62, M71, M72 },
ProcedureLog
}, new JsonSerializerOptions { WriteIndented = true });
object payload = method.Contains("吸湿透水汽", StringComparison.Ordinal)
? new
{
Result = result,
Masses = new
{
Trial1 = new { M11, M12, M21, M22, M31, M32, M41, M42, M51, M52, M61, M62, M71, M72 },
Trial2 = new { M11 = M11Second, M12 = M12Second, M21 = M21Second, M22 = M22Second, M31 = M31Second, M32 = M32Second, M41 = M41Second, M42 = M42Second, M51 = M51Second, M52 = M52Second, M61 = M61Second, M62 = M62Second, M71 = M71Second, M72 = M72Second }
},
ProcedureLog
}
: new
{
Result = result,
WarmthInputs = new
{
Cycle1 = new { EnergyKilojoules = WarmthEnergyKilojoules, Seconds = WarmthSeconds },
Cycle2 = new { EnergyKilojoules = WarmthEnergyKilojoulesSecond, Seconds = WarmthSecondsSecond }
},
ProcedureLog
};
var data = JsonSerializer.Serialize(payload, new JsonSerializerOptions { WriteIndented = true });
return await _repository.SaveAsync(new TestRunRecord(
0,

View File

@@ -33,7 +33,7 @@
<TextBlock Text="标准控制点" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="吸湿透水汽:泵流量 (5.0±0.3) cm³/h周期 (180±1) min" TextWrapping="Wrap"/>
<TextBlock Text="称重精确到 0.01 gm180 应在 15±0.9 g 范围内" TextWrapping="Wrap"/>
<TextBlock Text="结果T180* 为透水汽性能XT180* 为吸湿透水汽性能" TextWrapping="Wrap"/>
<TextBlock Text="结果:两次 T180*、XT180* 取平均,最终分别保留两位小数" TextWrapping="Wrap"/>
<TextBlock Text="保暖性能:假脚 (38±1) ℃,连续 2 个 180 min 周期" TextWrapping="Wrap"/>
</StackPanel>
</Border>
@@ -41,18 +41,22 @@
<Border Background="{DynamicResource AppCardBrush}" BorderBrush="{DynamicResource AppBorderBrush}" BorderThickness="1" CornerRadius="6" Padding="18">
<StackPanel Spacing="8">
<TextBlock Text="保暖性能输入" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="180 min 能量 P (kJ)" Foreground="#5B6775"/>
<TextBlock Text="第1周期 180 min 能量 P (kJ)" Foreground="#5B6775"/>
<TextBox Text="{Binding WarmthEnergyKilojoules}" sukiTheme:TextBoxExtensions.Unit="kJ"/>
<TextBlock Text="周期 t (s)" Foreground="#5B6775"/>
<TextBlock Text="第1周期 t (s)" Foreground="#5B6775"/>
<TextBox Text="{Binding WarmthSeconds}" sukiTheme:TextBoxExtensions.Unit="s"/>
<TextBlock Text="第2周期 180 min 能量 P (kJ)" Foreground="#5B6775"/>
<TextBox Text="{Binding WarmthEnergyKilojoulesSecond}" sukiTheme:TextBoxExtensions.Unit="kJ"/>
<TextBlock Text="第2周期 t (s)" Foreground="#5B6775"/>
<TextBox Text="{Binding WarmthSecondsSecond}" sukiTheme:TextBoxExtensions.Unit="s"/>
</StackPanel>
</Border>
</StackPanel>
<Grid Grid.Column="1" RowDefinitions="Auto,Auto,*">
<StackPanel Grid.Column="1" Spacing="14">
<Border Background="{DynamicResource AppCardBrush}" BorderBrush="{DynamicResource AppBorderBrush}" BorderThickness="1" CornerRadius="6" Padding="18">
<StackPanel Spacing="10">
<TextBlock Text="吸湿透水汽称重输入" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="吸湿透水汽称重输入 - 第1次" FontSize="18" FontWeight="SemiBold"/>
<Grid ColumnDefinitions="*,*,*,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock Text="m11 皮肤前"/>
<TextBox Grid.Row="1" Text="{Binding M11}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
@@ -89,7 +93,46 @@
</StackPanel>
</Border>
<Border Grid.Row="1" Background="{DynamicResource AppCardBrush}" BorderBrush="{DynamicResource AppBorderBrush}" BorderThickness="1" CornerRadius="6" Padding="18" Margin="0,14,0,0">
<Border Background="{DynamicResource AppCardBrush}" BorderBrush="{DynamicResource AppBorderBrush}" BorderThickness="1" CornerRadius="6" Padding="18">
<StackPanel Spacing="10">
<TextBlock Text="吸湿透水汽称重输入 - 第2次" FontSize="18" FontWeight="SemiBold"/>
<Grid ColumnDefinitions="*,*,*,*" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<TextBlock Text="m11 皮肤前"/>
<TextBox Grid.Row="1" Text="{Binding M11Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="1" Text="m12 皮肤后"/>
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding M12Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="2" Text="m21 袜前"/>
<TextBox Grid.Column="2" Grid.Row="1" Text="{Binding M21Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="3" Text="m22 袜后"/>
<TextBox Grid.Column="3" Grid.Row="1" Text="{Binding M22Second}" Margin="0,0,0,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Row="2" Text="m31 鞋前"/>
<TextBox Grid.Row="3" Text="{Binding M31Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="1" Grid.Row="2" Text="m32 鞋后"/>
<TextBox Grid.Column="1" Grid.Row="3" Text="{Binding M32Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="2" Grid.Row="2" Text="m41 鞋垫前"/>
<TextBox Grid.Column="2" Grid.Row="3" Text="{Binding M41Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="3" Grid.Row="2" Text="m42 鞋垫后"/>
<TextBox Grid.Column="3" Grid.Row="3" Text="{Binding M42Second}" Margin="0,0,0,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Row="4" Text="m51 C1前"/>
<TextBox Grid.Row="5" Text="{Binding M51Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="1" Grid.Row="4" Text="m52 C1后"/>
<TextBox Grid.Column="1" Grid.Row="5" Text="{Binding M52Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="2" Grid.Row="4" Text="m61 C2前"/>
<TextBox Grid.Column="2" Grid.Row="5" Text="{Binding M61Second}" Margin="0,0,10,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="3" Grid.Row="4" Text="m62 C2后"/>
<TextBox Grid.Column="3" Grid.Row="5" Text="{Binding M62Second}" Margin="0,0,0,8" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Row="6" Text="m71 C3前"/>
<TextBox Grid.Row="7" Text="{Binding M71Second}" Margin="0,0,10,0" sukiTheme:TextBoxExtensions.Unit="g"/>
<TextBlock Grid.Column="1" Grid.Row="6" Text="m72 C3后"/>
<TextBox Grid.Column="1" Grid.Row="7" Text="{Binding M72Second}" Margin="0,0,10,0" sukiTheme:TextBoxExtensions.Unit="g"/>
</Grid>
</StackPanel>
</Border>
<Border Background="{DynamicResource AppCardBrush}" BorderBrush="{DynamicResource AppBorderBrush}" BorderThickness="1" CornerRadius="6" Padding="18">
<StackPanel Spacing="8">
<TextBlock Text="流程记录" FontSize="18" FontWeight="SemiBold"/>
<ItemsControl ItemsSource="{Binding ProcedureLog}">
@@ -101,7 +144,7 @@
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</StackPanel>
</Grid>
</ScrollViewer>
</UserControl>