using AutoMapper;
using FLY.Thick.Base.IService;
using FObjBase;
using Misc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
namespace FLY.Thick.Base.Server
{
//1.剔除 偏离平均值 大于 设定值
//2.权重 滤波
public class Reject : IRejectService, INotifyPropertyChanged
{
public bool Enable { get; set; }
///
/// 规格范围, (value - Target)/Target > LimitRangeRatio 就会被剔除
///
public double LimitRangeRatio { get; set; }
public double ThresholdRatio { get; set; }
public int SmoothRange { get; set; }
public int RejectRange { get; set; }
///
/// 调试数据更新时间,用于让客户端 决定什么时候 下载调试数据
///
public DateTime DebugUpdateTime { get; private set; }
private RejectDebugData rejectDebug;
private string param_path = "reject.json";
public Reject()
{
SetDefault();
}
public Reject(string param_path)
{
if (!string.IsNullOrEmpty(param_path))
this.param_path = param_path;
SetDefault();
Load();
}
void SetDefault()
{
Enable = false;
LimitRangeRatio = 0.3;
ThresholdRatio = 0.93;
SmoothRange = 10;
RejectRange = 300;
}
public bool Load()
{
return RejectJsonDb.Load(param_path, this);
}
public bool Save()
{
return RejectJsonDb.Save(param_path, this);
}
public void Apply()
{
Save();
}
public void DoFrameFilter(double target, int posOfGrid, int start_grid, double[] frame)
{
var rejectDatas = (double[])frame.Clone();
int smoothRange = SmoothRange / posOfGrid;
if (smoothRange <= 0) smoothRange = 1;
int len = frame.Count();
var filterDatas = new double[len];
//滤波
for (int i = 0; i < len; i++)
{
int b = i - smoothRange;
int e = i + smoothRange;
if (b < 0) b = 0;
if (e >= len) e = len - 1;
List datas = new List();
for (int j = b; j <= e; j++)
datas.Add(rejectDatas[j]);
filterDatas[i] = datas.AverageNoNull();
}
double threshold = target * ThresholdRatio;
double limitRange = LimitRangeRatio * target;
bool[] bfilterdats = new bool[len];
//阀值剔除
for (int i = 0; i < len; i++)
{
if (!double.IsNaN(rejectDatas[i]))
{
if (rejectDatas[i] < threshold)
{
bfilterdats[i] = true;
}
else if (Math.Abs(target - rejectDatas[i]) > limitRange)
{
bfilterdats[i] = true;
}
}
}
int reject_b_idx = -1;
int reject_e_idx = -1;
//半径内全部删除
int reject_range = RejectRange / posOfGrid;
if (reject_range < 0)
reject_range = 0;
for (int i = 0; i < len; i++)
{
if (!bfilterdats[i])
{
//之前有需要剔除的
if (reject_b_idx != -1)
{
int b = reject_b_idx - reject_range;
int e = reject_e_idx + reject_range;
if (b < 0) b = 0;
if (e >= len) e = len - 1;
for (int j = b; j <= e; j++)
{
rejectDatas[j] = double.NaN;
}
reject_b_idx = -1;
i = e;
}
}
else
{
if (reject_b_idx == -1)
{
reject_b_idx = i;
}
reject_e_idx = i;
}
}
if (reject_b_idx != -1)
{
int b = reject_b_idx - reject_range;
int e = reject_e_idx + reject_range;
if (b < 0) b = 0;
if (e >= len) e = len - 1;
for (int j = b; j <= e; j++)
{
rejectDatas[j] = double.NaN;
}
reject_b_idx = -1;
}
if (Enable)
{
Array.Copy(rejectDatas, 0, frame, 0, len);
}
var rejectDebug = new RejectDebugData
{
posOfGrid = posOfGrid,
start_grid = start_grid,
target = target,
filterDatas = filterDatas,
rejectDatas = rejectDatas,
};
this.rejectDebug = rejectDebug;
this.DebugUpdateTime = DateTime.Now;
}
public void GetDebugData(AsyncCBHandler asyncDelegate, object asyncContext)
{
asyncDelegate?.Invoke(asyncContext, rejectDebug);
}
#region INotifyPropertyChanged 成员
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public class RejectJsonDb
{
static Mapper Mapper { get; } = new AutoMapper.Mapper(new MapperConfiguration(c =>
{
c.CreateMap().ReverseMap();
}));
public static bool Save(string file_path, Reject src)
{
try
{
var p = Mapper.Map(src);
File.WriteAllText(file_path, JsonConvert.SerializeObject(p, Formatting.Indented));
return true;
}
catch
{
//异常,没有json 编码失败
}
return false;
}
public static bool Load(string file_path, Reject src)
{
try
{
if (File.Exists(file_path))
{
string json = File.ReadAllText(file_path);
var p = JsonConvert.DeserializeObject(json);
Mapper.Map(p, src);
}
}
catch
{
//异常,没有json 解码失败
}
return false;
}
public bool Enable { get; set; }
public double LimitRangeRatio { get; set; }
public double ThresholdRatio { get; set; }
public int SmoothRange { get; set; }
public int RejectRange { get; set; }
}
}