Files
WC-CZGKJ/SCADA/Core/WeightCalibrationHelper.cs

139 lines
4.3 KiB
C#

using DynamicExpresso;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace MesWork
{
/// <summary>
/// 重量标定公式计算工具。
/// </summary>
public static class WeightCalibrationHelper
{
private class CalibrationCache
{
public string ToolName;
public string Formula;
public string Description;
public DateTime LoadedAt;
}
private static readonly object CacheLock = new object();
private static readonly Dictionary<string, CalibrationCache> Cache = new Dictionary<string, CalibrationCache>(StringComparer.OrdinalIgnoreCase);
private static readonly TimeSpan CacheLife = TimeSpan.FromSeconds(3);
public static bool Apply(string opName, decimal rawWeight, out decimal calibratedWeight, out string formula, out string message)
{
calibratedWeight = rawWeight;
formula = "x";
message = "";
if (!TryGetConfig(opName, rawWeight, out CalibrationCache config, out string queryMsg))
{
if (!string.IsNullOrWhiteSpace(queryMsg))
{
message = queryMsg;
return false;
}
formula = "x";
calibratedWeight = rawWeight;
return true;
}
formula = NormalizeFormula(config.Formula);
return TryEvaluateFormula(formula, rawWeight, out calibratedWeight, out message);
}
public static void ClearCache()
{
lock (CacheLock)
{
Cache.Clear();
}
}
public static bool ValidateFormula(string formula, out string message)
{
decimal _;
return TryEvaluateFormula(NormalizeFormula(formula), 1M, out _, out message);
}
private static string NormalizeFormula(string formula)
{
return string.IsNullOrWhiteSpace(formula) ? "" : formula.Trim();
}
private static bool TryEvaluateFormula(string formula, decimal xValue, out decimal result, out string message)
{
result = xValue;
message = "";
if (string.IsNullOrWhiteSpace(formula))
{
message = "计算公式不能为空,至少填写 x";
return false;
}
try
{
var interpreter = new Interpreter();
interpreter.Reference(typeof(Math));
double x = Convert.ToDouble(xValue);
interpreter.SetVariable("x", x);
interpreter.SetVariable("X", x);
object value = interpreter.Eval(formula);
if (value == null)
{
message = "计算公式未返回数值";
return false;
}
result = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
return true;
}
catch (Exception err)
{
message = $"计算公式错误:{err.Message}";
return false;
}
}
private static bool TryGetConfig(string opName, decimal rawWeight, out CalibrationCache config, out string message)
{
config = null;
message = "";
string station = string.IsNullOrWhiteSpace(opName) ? "" : opName.Trim();
string key = station + "|" + rawWeight.ToString("F3", CultureInfo.InvariantCulture);
lock (CacheLock)
{
if (Cache.TryGetValue(key, out config) && DateTime.Now - config.LoadedAt < CacheLife)
{
return true;
}
}
if (!B_DB_Opera.QueryToolCalibration(station, rawWeight, out string toolName, out string formula, out string description, out message))
{
return false;
}
config = new CalibrationCache
{
ToolName = toolName,
Formula = formula,
Description = description,
LoadedAt = DateTime.Now
};
lock (CacheLock)
{
Cache[key] = config;
}
return true;
}
}
}