公司項目有一個需求,通過稱重貨架來計算 物資的數量,在實際使用的過程中 人員每次從 稱重貨架上拿區的物品過程是 不穩定且確定性的
如果使用定時的方式獲取稱重貨架的值 可能取到的值是某個時間點的瞬時重量 不是實際的重量
現通過算法實現 獲取到的是稱重貨架 在穩定一個固定時間段 後返回的值
記錄一個時間點的穩定值,
下一次 變量波動後,
記錄第n次 後最終穩定下來的值 m5
實現方案
創建 StabeDataHandle 類
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StabeDataHandle {
/**
* 指定時間範圍 t
* 這個值需要大於秤盤發送數據的時間間隔
*/
public final static Long dealyTime = 6L;
/**
* 誤差範圍
*/
public final static Double scope = 10.00;
public static Map<String, List<StabeDataModel>> lists = new HashMap<>();
private static StabeDataHandle stabeDataUtil = new StabeDataHandle();
private StabeDataHandle() {
}
public static StabeDataHandle getInstance() {
return stabeDataUtil;
}
public Double[] getData(String id, Double val) {
Double[] res = new Double[2]; //返回數組 上一次穩定值和當前穩定值
Long time = System.currentTimeMillis() / 1000;
List<StabeDataModel> data = lists.get(id);
if (data == null) {
//初始化
data = new ArrayList<StabeDataModel>();
data.add(new StabeDataModel(time, val,0L));
} else {
StabeDataModel original = data.get(0);
Long dt = time - dealyTime;
//先把當前傳過來的值 放到數組中,和以前的數據一起做處理
data.add(new StabeDataModel(time, val,time-original.getTime()));
//當前時間-指定時間 > 最開始時間 說明有足夠時間範圍,可以計算了
if (dt >= original.getTime()) {
//獲取指定時間範圍內的值 即A4點的數據
int index = BinarySearch(data, dt);
if(index == -1){
//沒找到 繼續添加值 (這個情況 可能是秤盤 壞了,沒有在固定時間內返回值給我)
System.out.println("沒找到 繼續添加;可能是秤盤 壞了,沒有在固定時間內發送值給我");
//data.add(new StabeDataModel(time, val,time-original.getTime()));
}else{
//data.add(new StabeDataModel(time, val,time-original.getTime()));
//判斷這個時間範圍內的值 是否全部相等 (差值在一定誤差範圍內默認是相等的 )
boolean flag = stableVerify(data, index, scope);
if (flag) {
//如果相等,證明找到了 第二個穩定值
//重置 data
data = new ArrayList<StabeDataModel>();
data.add(new StabeDataModel(time, val,0L));
res[0] = original.getVal();
res[1] = val;
}
}
}
}
lists.put(id, data);
testData(id);
return res;
}
/**
* 計算 某段時間範圍內的數據 是否都在誤差範圍內
* @param datas
* @param index 開始位置
* @param scope 誤差範圍
* @return
*/
private static boolean stableVerify(List<StabeDataModel> datas, int index, Double scope) {
Double max = datas.get(index).getVal();
Double min = datas.get(index).getVal();
//計算最值
for (int i = index; i < datas.size(); i++) {
if (datas.get(i).getVal() > max) {
max = datas.get(i).getVal();
}
if (datas.get(i).getVal() < min) {
min = datas.get(i).getVal();
}
}
if (max - min <= scope) {
return true;
}
return false;
}
/**
* 二分法查找<br/>
* ps: 如果 datas.size()==2 說明秤盤在穩定時間範圍外發給我的一條數據 將被認爲是有效數據 系統將進入第二次循環
* @param datas,
* @param val
* @return
*/
private static int BinarySearch(List<StabeDataModel> datas, Long val) {
int min = 0;
int max = datas.size() - 1;
while (min <= max) {
int middle = (min + max) / 2;
//條件判斷
if (val >= datas.get(middle).getTime()) {
//int next = (middle + 1 > max)?max:middle + 1;
if (val <= datas.get(middle + 1).getTime()) {
return middle;
}
}
//二分判斷 val在中位的左邊還是右邊
if (val > datas.get(middle).getTime()) {
min = middle + 1;
} else {
max = middle - 1;
}
}
return -1;
}
private void testData(String id) {
System.out.println("------1-------");
List<StabeDataModel> data = lists.get(id);
for (StabeDataModel datum : data) {
System.out.println(datum);
}
System.out.println("------2-------");
}
}
實體類 StabeDataModel
package com.xue.util;
public class StabeDataModel {
private String id;
private Long key;
private Double val;
private Long time;
public StabeDataModel(Long time, Double val, Long key) {
this.key = key;
this.val = val;
this.time = time;
}
@Override
public String toString() {
return "StabeDataModel{" +
"id='" + id + '\'' +
", key=" + key +
", val=" + val +
", time=" + time +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Long getKey() {
return key;
}
public void setKey(Long key) {
this.key = key;
}
public Double getVal() {
return val;
}
public void setVal(Double val) {
this.val = val;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
}
測試
//測試
@RequestMapping("/dataTest")
@ResponseBody
public Object dataTest(@RequestParam HashMap params){
HashMap<String, Object> map = new HashMap<>();
String id = (String) params.get("id");
Double val = Double.valueOf(params.get("val").toString());
Double[] res = StabeDataHandle.getInstance().getData(id, val);
map.put("data",StabeDataHandle.lists);
map.put("result",res);
return map;
}
結果
{
"result": [
null,
null
],
"data": {
"123": [
{
"id": null,
"key": 0,
"val": 562,
"time": 1573312026
},
{
"id": null,
"key": 6,
"val": 2,
"time": 1573312032
},
{
"id": null,
"key": 10,
"val": 2,
"time": 1573312036
},
{
"id": null,
"key": 13,
"val": 255,
"time": 1573312039
},
{
"id": null,
"key": 20,
"val": 2524,
"time": 1573312046
},
{
"id": null,
"key": 24,
"val": 25247,
"time": 1573312050
},
{
"id": null,
"key": 27,
"val": 25247,
"time": 1573312053
}
]
}
}
下一次 重置數據,並返回變化值