Files
controller-wisetopvue/src/store/modules/task/content/actions/chartAct.js
T
peterlu14 5e761d68b4 feat: refine UI behavior and enhance test compatibility
- Clear input value after confirming in the SaveConfigModal component
- Add a check for undefined grid source before removing series in chart actions

Signed-off-by: peterlu14 <peterlu810516@gmail.com>
2023-12-15 11:59:53 +08:00

1158 lines
42 KiB
JavaScript

import types from '@/store/modules/task/content/types'
import newDataZoom from '@/factories/chart/dataZoomFactory'
import newChart from '@/factories/chart/chartFactory'
import newTooltip from '@/factories/chart/tooltipFactory'
import newSeries from '@/factories/chart/seriesFactory'
import { dataStreamBuffer } from '@/data/task/DataStreamBuffer'
import { taskInfo } from '@/data/task/TaskInfo'
import global_ from '@/data/global/global'
import { IIRFilter } from '@/data/task/filter/IIRFilter.js'
import config from '@/data/config-table/index'
const typePath = types.chart
const chartActs = {
/**
* init chartData from cache (cache will only record non-default chart)
*
**/
[typePath.initCustomizedFromCache]: async ({ state, getters, commit, dispatch }, payload) => {
// const { controllerID } = payload
// const cacheData = await localforage.getItem('chart_data_' + controllerID)
// if (cacheData !== null) {
// // use ID to create new chart by cache
// for (const _chart of Object.values(cacheData)) {
// dispatch(typePath.add, {
// chartID: _chart.chartID,
// maxDots: _chart.maxDots,
// gridLength: _chart.grid.length,
// })
// for (let gridIndex = 0; gridIndex < _chart.grid.length; gridIndex++) {
// if (gridIndex in _chart.gridSource) {
// dispatch(typePath.registerFromCache, {
// chartID: _chart.chartID,
// gridIndex: gridIndex,
// gridSource: _chart.gridSource[gridIndex],
// })
// }
// }
// state.chartData[_chart.chartID].mappingID = _chart.mappingID
// state.chartData[_chart.chartID].createdBy = 'manual'
// }
// dispatch(typePath.refreshPanel)
// }
},
/**
* set chartData to cache (cache will only record non-default chart)
*
*/
[typePath.saveToCache]: async ({ state, getters, commit, dispatch }, payload) => {
// const { controllerID } = payload
// const _chartData = {}
// for (const [_id, _chart] of Object.entries(state.chartData)) {
// // manual chart clear series data
// if (_chart.createdBy === 'manual') {
// _chartData[_id] = JSON.parse(JSON.stringify(_chart))
// _chartData[_id].series.map((ele) => { ele.data.length = 0 })
// }
// }
// await localforage.setItem('chart_data_' + controllerID, _chartData)
},
/*
* add chartID to chartData
* @param {String} chartID
* @param {Number} maxDots
* @param {Number} gridLength
* @return {object} : chart data
*/
[typePath.add]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, maxDots, gridLength } = payload
if (state.chartData[chartID] == null) {
state.chartData[chartID] = newChart(chartID, Object.keys(state.chartData).length)
state.chartData[chartID].maxDots = maxDots
state.chartData[chartID].tooltip = newTooltip()
dispatch(typePath.updateGridList, { chartID: chartID, length: gridLength })
return state.chartData[chartID]
} else {
return state.chartData[chartID]
}
},
/**
* register source channel setting from cache
*
* @param {String} chartID
* @param {Number} gridIndex
* @param {Object} gridSource
*/
[typePath.registerFromCache]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, gridIndex, gridSource } = payload
// one gridSource may have multiple axis (i.e. 疊圖)
gridSource.forEach(grid => {
const xAxisInfo = parseGridSourceAxis(grid.xSource)
const yAxisInfo = parseGridSourceAxis(grid.ySource)
dispatch(typePath.register, {
chartID: chartID,
gridIndex: gridIndex,
deviceNameX: xAxisInfo.deviceName,
deviceIDX: xAxisInfo.deviceID,
deviceX: xAxisInfo,
channelX: xAxisInfo.channel,
deviceNameY: yAxisInfo.deviceName,
deviceIDY: yAxisInfo.deviceID,
deviceY: yAxisInfo,
channelY: yAxisInfo.channel,
formula: null,
})
})
},
/**
* register device-channel to chartData
*
* @param {String} chartID
* @param {Number} gridIndex
* @param {String} deviceNameX
* @param {String} deviceIDX
* @param {Number} channelX
* @param {String} deviceNameY
* @param {String} deviceIDY
* @param {Number} channelY
* @param {String} formula
* @return {object} : new registered chart
*/
[typePath.register]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, gridIndex, deviceNameX, deviceIDX, deviceX, channelX, deviceNameY, deviceIDY, deviceY, channelY, formula } = payload
console.log('register', chartID, gridIndex, deviceNameX, deviceIDX, deviceX, channelX, deviceNameY, deviceIDY, deviceY, channelY, formula)
const sourceList = [
{
name: deviceNameX,
mac_address: (deviceX) ? deviceX.mac_address : deviceX,
channel: channelX,
},
{
name: deviceNameY,
mac_address: (deviceY) ? deviceY.mac_address : deviceY,
channel: channelY,
},
]
if (state.chartData[chartID] == null) {
return false
}
let xAxisType
let yAxisType
let xAxisSource
let yAxisSource
// formulaSource
const formulaSource = []
let legendName
if (formula == null) {
legendName = getLegendName(sourceList, formula, state.deviceListNew)
} else {
legendName = getLegendName(sourceList, formula.id, state.deviceListNew)
}
if (formula == null) {
switch (sourceList[0].name) {
case 'Time':
xAxisType = 'time'
xAxisSource = ['Time', 'Time']
break
default:
xAxisType = 'value'
xAxisSource = [sourceList[0].mac_address, sourceList[0].channel]
break
}
switch (sourceList[1].name) {
case 'Time':
yAxisType = 'time'
yAxisSource = [-1, -1]
break
default:
yAxisType = 'value'
yAxisSource = [sourceList[1].mac_address, sourceList[1].channel]
break
}
} else {
sourceList.forEach(source => {
formulaSource.push([source.id, source.channel])
})
xAxisType = 'time'
yAxisType = 'value'
}
// register legendName
if (state.chartData[chartID].legend.data.indexOf(legendName) >= 0) {
// have been registered
return false
}
state.chartData[chartID].legend.data.push(legendName)
// if AxisIndex != -1 then add new axis into list
let _xAxisIndex = -1
let _yAxisIndex = -1
// the grid have exist, so just use the axis in grid
for (let i = 0; i < state.chartData[chartID].xAxis.length; i++) {
if (state.chartData[chartID].xAxis[i].gridIndex === gridIndex) {
_xAxisIndex = i
}
}
for (let i = 0; i < state.chartData[chartID].yAxis.length; i++) {
if (state.chartData[chartID].yAxis[i].gridIndex === gridIndex) {
_yAxisIndex = i
}
}
// create new axis
if (_xAxisIndex === -1) {
state.chartData[chartID].xAxis.push(makeXAxis(gridIndex, xAxisType, channelX))
_xAxisIndex = state.chartData[chartID].xAxis.length - 1
}
if (_yAxisIndex === -1) {
state.chartData[chartID].yAxis.push(makeYAxis(gridIndex, yAxisType, channelY))
_yAxisIndex = state.chartData[chartID].yAxis.length - 1
}
state.chartData[chartID].chartXMode = state.chartData[chartID].xAxis[_xAxisIndex].type
state.chartData[chartID].chartYMode = state.chartData[chartID].yAxis[_yAxisIndex].type
// update dataZoom AxisIndex list
const dataZoomXAxisIndex = Array.apply(null, { length: state.chartData[chartID].xAxis.length }).map(Number.call, Number)
const dataZoomYAxisIndex = Array.apply(null, { length: state.chartData[chartID].yAxis.length }).map(Number.call, Number)
if (state.chartData[chartID].dataZoom == null) {
state.chartData[chartID].dataZoom = newDataZoom()
}
state.chartData[chartID].dataZoom[0].xAxisIndex = dataZoomXAxisIndex
state.chartData[chartID].dataZoom[1].xAxisIndex = dataZoomXAxisIndex
state.chartData[chartID].dataZoom[2].yAxisIndex = dataZoomYAxisIndex
// register series
const _series = newSeries('line', legendName, _xAxisIndex, _yAxisIndex, xAxisSource, yAxisSource, formula, formulaSource)
// const _seriesIndex = state.chartData[chartID].series.length
state.chartData[chartID].series.push(_series)
// state.chartData[chartID].xAxis[_xAxisIndex].seriesIndex.push(_seriesIndex)
// state.chartData[chartID].yAxis[_yAxisIndex].seriesIndex.push(_seriesIndex)
// state.chartData[chartID].xAxis[_xAxisIndex].boundaryGap = [0, '5%']
// state.chartData[chartID].yAxis[_yAxisIndex].boundaryGap = [0, '10%']
// console.log(state.chartData[chartID])
// set xAxis format
// TODO: need to get the time unit for the CanvasChart
// register series into grid
const _axisList = []
const sourceArray = []
if (formula == null) {
sourceList.forEach((source, index) => {
let _axis = 'X'
if (index !== 0) {
_axis = 'Y'
}
sourceArray.push(source)
switch (source.name) {
case 'Time':
_axisList.push(_axis + ' AXIS = TIME')
break
case 'Neulive':
dataStreamBuffer.register(source.id, source.channel)
_axisList.push(_axis + ' AXIS = NEULIVE ' + source.id + ' CHANNEL ' + source.channel)
break
case 'Elite':
dataStreamBuffer.register(chartID, source.mac_address, source.channel)
_axisList.push(_axis + ' AXIS = ELITE ' + source.id + ' CHANNEL ' + source.channel)
break
case 'EliteEIS':
// eslint-disable-next-line no-case-declarations
// const device = state.deviceListNew.find((ele) => String(ele.memory_board) === String(source.id))
// if (device === undefined) break
// if (Number(device.configuration.MODE) === 0 || Number(device.configuration.MODE) === 5) {
// state.chartData[chartID].series[state.chartData[chartID].series.length - 1].showSymbol = true
// state.chartData[chartID].series[state.chartData[chartID].series.length - 1].showAllSymbol = true
// }
dataStreamBuffer.register(chartID, source.mac_address, source.channel)
switch (source.channel) {
case 1:
_axisList.push(_axis + ' AXIS = ELITEEIS ' + source.id + ' CHANNEL ' + source.channel)
break
default:
_axisList.push(_axis + ' AXIS = ELITEEIS ' + source.id + ' CHANNEL ' + source.channel)
break
}
break
default:
dataStreamBuffer.register(chartID, source.mac_address, source.channel)
_axisList.push(_axis + ' AXIS = DEVICE ' + source.id + ' CHANNEL ' + source.channel)
break
}
})
} else {
_axisList.push('X AXIS = TIME')
_axisList.push('Y AXIS = FORMULA' + formula.id)
sourceList.forEach(source => {
dataStreamBuffer.register(chartID, source.id, source.channel)
})
}
const _gridSeries = {
name: legendName,
// xAxis: _axisList[0],
// yAxis: _axisList[1],
xSource: sourceArray[0],
ySource: sourceArray[1],
}
if (state.chartData[chartID].gridSource[gridIndex] == null) {
state.chartData[chartID].gridSource[gridIndex] = []
}
if (!state.chartData[chartID].gridSource[gridIndex].some(el => el.name === _gridSeries.name)) {
state.chartData[chartID].gridSource[gridIndex].push(_gridSeries)
}
// assign mappingID with device ID
if (deviceX) {
if (state.chartData[chartID].mappingID.indexOf(deviceX.mac_address) === -1 && deviceX.mac_address) {
state.chartData[chartID].mappingID.push(deviceX.mac_address)
}
}
if (deviceY) {
if (state.chartData[chartID].mappingID.indexOf(deviceY.mac_address) === -1 && deviceY.mac_address) {
state.chartData[chartID].mappingID.push(deviceY.mac_address)
}
}
return state.chartData[chartID]
},
/**
* update specific chart grid length
*
* @param {String} chartID
* @param {Number} length
*/
[typePath.updateGridList]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, length } = payload
state.chartData[chartID].grid.length = 0
for (let i = 0; i < length; i++) {
state.chartData[chartID].grid.push(makeGrid(i, length))
}
},
/**
* refresh chart data from data stream buffer
*
* @param {String} chartID
*/
[typePath.refreshData]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID } = payload
if (state.chartData[chartID] == null) {
return false
}
// for each series registered
state.chartData[chartID].series.forEach(series => {
if (series.formula != null) {
let zeroBatch = false
series.formulaSource.forEach(source => {
if (dataStreamBuffer.getByChartID(chartID)[source[0]][source[1]].length === 0) {
zeroBatch = true
}
})
if (zeroBatch) {
series.formulaSource.forEach(source => {
if (dataStreamBuffer.getByChartID(chartID)[source[0]][source[1]].length > 0) {
dataStreamBuffer.merge(chartID, source[0], source[1])
}
})
return false
} else {
const popData = []
const indexNow = []
const indexArray = []
series.formulaSource.forEach((source, index) => {
const _popData = dataStreamBuffer.pop(chartID, source[0], source[1])
popData.push({
data: _popData,
indexRaw: index,
})
indexNow.push(0)
})
// form min to max
popData.sort((a, b) => {
if (Object.keys(a.data).length > Object.keys(b.data).length) {
return 1
} else {
return -1
}
})
popData.forEach((_popData, index) => {
if (popData[index + 1] != null) {
indexArray.push(getIndexArrayForBalenceSampleRate([], Object.keys(popData[index + 1].data).length - Object.keys(popData[index].data).length, Object.keys(popData[index].data).length))
}
})
let value
switch (series.formula.type) {
case 'Sheet Resistance':
for (let i = 0; i < popData[0].data.length; i++) {
let dataI
let dataV
dataV = popData[0].indexRaw === 0 ? popData[0].data[i].data : popData[1].data[indexNow[1]].data
dataI = popData[0].indexRaw === 1 ? popData[0].data[i].data : popData[1].data[indexNow[1]].data
// console.log(dataV, dataI, popData[0], popData[1])
// 4.5324 * 1000
value = parseFloat(dataV / dataI) * 4532.4
series.data.push([popData[1].data[indexNow[1]].time, value])
indexNow[1]++
if (series.dataYMax < value || series.dataYMax == null) {
series.dataYMax = value
}
if (series.dataYMin > value || series.dataYMin == null) {
series.dataYMin = value
}
indexArray.forEach(pattern => {
if ((i + 1) % pattern[0] === 0) {
for (let j = 0; j < pattern[1]; j++) {
if (popData[1].data[Object.keys(popData[1].data)[indexNow[1]]] != null) {
dataV = popData[0].indexRaw === 0 ? popData[0].data[i].data : popData[1].data[indexNow[1]].data
dataI = popData[0].indexRaw === 1 ? popData[0].data[i].data : popData[1].data[indexNow[1]].data
// console.log(dataV, dataI, popData[0], popData[1])
value = parseFloat(dataV / dataI) * 4532.4
series.data.push([popData[1].data[indexNow[1]].time, value])
indexNow[1]++
if (series.dataYMax < value || series.dataYMax == null) {
series.dataYMax = value
}
if (series.dataYMin > value || series.dataYMin == null) {
series.dataYMin = value
}
}
}
}
})
}
series.formula.dataNow = value.toFixed(3)
break
}
// series data list shift
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
// axis shift
if (series.data.length > 0) {
state.chartData[chartID].xAxis[series.xAxisIndex].max = series.data[series.data.length - 1][0]
state.chartData[chartID].xAxis[series.xAxisIndex].min = series.data[0][0]
const center = (series.dataYMax + series.dataYMin) / 2
const range = (series.dataYMax - series.dataYMin)
if (state.chartData[chartID].yAxis[series.yAxisIndex].max < center + (range * 2) || state.chartData[chartID].yAxis[series.yAxisIndex].max == null) {
state.chartData[chartID].yAxis[series.yAxisIndex].max = center + (range * 2)
}
if (state.chartData[chartID].yAxis[series.yAxisIndex].min > center - (range * 2) || state.chartData[chartID].yAxis[series.yAxisIndex].min == null) {
state.chartData[chartID].yAxis[series.yAxisIndex].min = center - (range * 2)
}
}
}
} else {
if (series.xAxisSource[0] === 'Time' && series.yAxisSource[0] === 'Time') {
return false
}
if (series.xAxisSource[0] === 'Time' || series.yAxisSource[0] === 'Time') {
// x axis is time, y axis is value, so only need a device-channel data stream
let popData = []
// get raw deviceID
const rawDeviceIDX = series.xAxisSource[0]
const rawDeviceIDY = series.yAxisSource[0]
// pop data
if (series.xAxisSource[0] === 'Time') {
popData = dataStreamBuffer.pop(chartID, rawDeviceIDY, series.yAxisSource[1])
} else {
popData = dataStreamBuffer.pop(chartID, rawDeviceIDX, series.xAxisSource[1])
}
popData.forEach(data => {
// const _popData = data.data
let _popData = Number(data.data)
series.filter.forEach(filter => {
if (filter.filter != null) {
_popData = IIRFilter.filter(filter.filter, _popData)
}
})
const _popTime = data.time
// series data is empty or popdata time > last series data time
if (series.xAxisSource[0] === 'Time') {
if (_popTime < 0) {
series.data.push([])
} else {
series.data.push([_popTime, _popData])
// get max/min value
if (series.dataYMax < _popData || series.dataYMax == null) {
series.dataYMax = _popData
}
if (series.dataYMin > _popData || series.dataYMin == null) {
series.dataYMin = _popData
}
}
} else {
if (_popTime < 0) {
series.data.push([])
} else {
series.data.push([_popData, _popTime])
// get max/min value
if (series.dataXMax < _popData || series.dataXMax == null) {
series.dataXMax = _popData
}
if (series.dataXMin > _popData || series.dataXMin == null) {
series.dataXMin = _popData
}
}
}
})
// series data list shift by time
if (series.data.length > 0) {
if (series.xAxisSource[0] === 'Time') {
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
} else if (series.yAxisSource[0] === 'Time') {
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
}
}
// axis shift
if (series.data.length > 0) {
if (series.xAxisSource[0] === 'Time') {
state.chartData[chartID].xAxis[series.xAxisIndex].max = series.data[series.data.length - 1][0]
state.chartData[chartID].xAxis[series.xAxisIndex].min = series.data[0][0]
} else {
state.chartData[chartID].yAxis[series.yAxisIndex].max = series.data[series.data.length - 1][1]
state.chartData[chartID].yAxis[series.yAxisIndex].min = series.data[0][1]
}
}
} else {
// x axis and y axis is value, so need two device-channel data stream and align
// get real deviceID from controller
const rawDeviceIDX = series.xAxisSource[0]
const rawDeviceIDY = series.yAxisSource[0]
// get real deviceID fault
if (rawDeviceIDX == null || rawDeviceIDY == null) {
return false
}
if (dataStreamBuffer.getByChartID(chartID)[rawDeviceIDX][series.xAxisSource[1]].length === 0 &&
dataStreamBuffer.getByChartID(chartID)[rawDeviceIDY][series.yAxisSource[1]].length === 0) {
// all of buffer is empty
return false
} else if (dataStreamBuffer.getByChartID(chartID)[rawDeviceIDX][series.xAxisSource[1]].length === 0 ||
dataStreamBuffer.getByChartID(chartID)[rawDeviceIDY][series.yAxisSource[1]].length === 0) {
// merge all batch from the buffer not empty
// const xLarge = dataStreamBuffer.getByChartID(chartID)[rawDeviceIDX][series.xAxisSource[1]].length > dataStreamBuffer.getByChartID(chartID)[rawDeviceIDY][series.yAxisSource[1]].length
// if (xLarge) {
// dataStreamBuffer.merge(chartID, rawDeviceIDX, series.xAxisSource[1])
// } else {
// dataStreamBuffer.merge(chartID, rawDeviceIDY, series.yAxisSource[1])
// }
return false
}
// get data from buffer
const popDataX = dataStreamBuffer.pop(chartID, rawDeviceIDX, series.xAxisSource[1])
const popDataY = dataStreamBuffer.pop(chartID, rawDeviceIDY, series.yAxisSource[1])
// data align
let indexArray = []
if (Math.abs(popDataX.length - popDataY.length) < 10) {
const lenBatch = popDataX.length > popDataY.length ? popDataY.length : popDataX.length
for (let i = 0; i < lenBatch; i++) {
const _popDataX = (popDataX[i].data)
const _popDataY = (popDataY[i].data)
if (_popDataY != null) {
// [data1, data2, time]
series.data.push([_popDataX, _popDataY, parseInt(popDataX[i].time)])
if (series.dataXMax < _popDataX || series.dataXMax == null) {
series.dataXMax = _popDataX
}
if (series.dataXMin > _popDataX || series.dataXMin == null) {
series.dataXMin = _popDataX
}
if (series.dataYMax < _popDataY || series.dataYMax == null) {
series.dataYMax = _popDataY
}
if (series.dataYMin > _popDataY || series.dataYMin == null) {
series.dataYMin = _popDataY
}
} else {
// the batch Y is empty
break
}
}
} else {
const xLarge = popDataX.length > popDataY.length
const popDataLarge = popDataX.length > popDataY.length ? popDataX : popDataY
const popDataSmall = popDataX.length > popDataY.length ? popDataY : popDataX
// get index array to know what time we need to copy a data to align its
indexArray = getIndexArrayForBalenceSampleRate([], popDataLarge.length - popDataSmall.length, popDataSmall.length)
let _index = 0
for (let i = 0; i < popDataSmall.length; i++) {
let _popDataX = xLarge ? (popDataLarge[_index].data) : (popDataSmall[i].data)
let _popDataY = xLarge ? (popDataSmall[i].data) : (popDataLarge[_index].data)
// [data1, data2, time]
series.data.push([_popDataX, _popDataY, parseInt(popDataLarge[_index].time)])
_index++
if (series.dataXMax < _popDataX || series.dataXMax == null) {
series.dataXMax = _popDataX
}
if (series.dataXMin > _popDataX || series.dataXMin == null) {
series.dataXMin = _popDataX
}
if (series.dataYMax < _popDataY || series.dataYMax == null) {
series.dataYMax = _popDataY
}
if (series.dataYMin > _popDataY || series.dataYMin == null) {
series.dataYMin = _popDataY
}
indexArray.forEach(pattern => {
if ((i + 1) % pattern[0] === 0) {
for (let j = 0; j < pattern[1]; j++) {
_popDataX = xLarge ? (popDataLarge[_index].data) : (popDataSmall[i].data)
_popDataY = xLarge ? (popDataSmall[i].data) : (popDataLarge[_index].data)
// [data1, data2, time]
if (_popDataX != null) {
series.data.push([_popDataX, _popDataY, parseInt(popDataLarge[_index].data)])
_index++
if (series.dataXMax < _popDataX || series.dataXMax == null) {
series.dataXMax = _popDataX
}
if (series.dataXMin > _popDataX || series.dataXMin == null) {
series.dataXMin = _popDataX
}
if (series.dataYMax < _popDataY || series.dataYMax == null) {
series.dataYMax = _popDataY
}
if (series.dataYMin > _popDataY || series.dataYMin == null) {
series.dataYMin = _popDataY
}
}
}
}
})
}
}
// series data list shift
if (series.data.length > state.chartData[chartID].maxDots) {
series.data.splice(0, series.data.length - state.chartData[chartID].maxDots)
}
}
}
})
const popCycle = dataStreamBuffer.pop(chartID, state.chartData[chartID].mappingID, 4)
if (popCycle.length) {
state.chartData[chartID].cycle = popCycle.at(-1).data
}
},
/**
* generate default chart
*
* @param {Array} _deviceList
* @param {String} _itemID
* @param {String} _chartID
* @param {String} _type
* @return {bool}
*/
[typePath.defaultChartGenerator]: async ({ state, getters, commit, dispatch }, payload) => {
const { _deviceList, _itemID, _chartID, _type, _reset } = payload
let item
_deviceList.forEach(_device => {
if (_itemID === _device.id) {
item = _device
}
})
taskInfo.getFormulaList().forEach(_formula => {
if (_itemID === _formula.id) {
item = _formula
}
})
if (item == null) {
return false
}
const _chartRegisterDevice = (chartID, device) => {
if (device.library_name.includes('Elite')) {
const setting = global_.getDefaultChartTypeByMode(device.configuration.MODE, device.library_name)
const xType = setting[0]
let xValue = setting[1]
const yType = setting[2]
let yValue = setting[3]
const xDevice = xType === 'Time' ? undefined : device
const yDevice = yType === 'Time' ? undefined : device
if (xType === 'Time') xValue = 'Time'
if (yType === 'Time') yValue = 'Time'
dispatch(typePath.register, {
chartID: chartID,
gridIndex: 0,
deviceNameX: xType,
deviceIDX: device.id,
deviceX: xDevice,
channelX: xValue,
deviceNameY: yType,
deviceIDY: device.id,
deviceY: yDevice,
channelY: yValue,
formula: null,
})
state.chartData[chartID].chartDevice = 'elite'
state.chartData[chartID].chartMode = device.configuration.MODE
}
}
const _chartRegisterFormula = (chartID, formula) => {
switch (formula.type) {
case 'Sheet Resistance':
dispatch(typePath.register, {
chartID: chartID,
gridIndex: 0,
deviceNameX: 'Elite',
deviceIDX: formula.I_device.id,
channelX: 1,
deviceNameY: 'Elite',
deviceIDY: formula.V_device.id,
channelY: 2,
formula: formula,
})
break
}
}
// TODO remove old buffer register
if (_chartID != null) {
// update only one
dispatch(typePath.reset, {
chartID: _chartID,
mappingID: state.chartData[_chartID].mappingID,
cardName: state.chartData[_chartID].cardName,
})
state.chartData[_chartID].mappingID = item.id
switch (_type) {
case 'device':
_chartRegisterDevice(_chartID, item)
break
case 'formula':
_chartRegisterFormula(_chartID, item)
break
}
} else {
// update all
let isSetting = false
for (const chartID in state.chartData) {
if (state.chartData[chartID].mappingID.includes(item.mac_address)) {
if (state.chartData[chartID].createdBy === 'default') {
isSetting = true
dispatch(typePath.reset, {
chartID: chartID,
mappingID: state.chartData[chartID].mappingID,
cardName: state.chartData[chartID].cardName,
reset: _reset,
})
switch (_type) {
case 'device':
_chartRegisterDevice(chartID, item)
break
case 'formula':
_chartRegisterFormula(chartID, item)
break
}
}
}
}
if (isSetting === false) {
return false
}
}
dispatch(typePath.refreshPanel)
return true
},
/**
* reset chart option
*
* @param {String} chartID
* @param {String} mappingID
* @param {String} cardName
*/
[typePath.reset]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, mappingID, cardName, reset } = payload
state.chartData[chartID].legend.data.length = 0
state.chartData[chartID].xAxis.length = 0
state.chartData[chartID].yAxis.length = 0
state.chartData[chartID].gridSource.length = 0
if (reset === undefined) {
if (state.chartData[chartID].series.data != null) {
state.chartData[chartID].series.data.length = 0
}
state.chartData[chartID].series.length = 0
}
if (mappingID == null) {
state.chartData[chartID].mappingID = []
}
if (cardName == null) {
state.chartData[chartID].cardName = 'Chart' + String(chartID)
}
state.chartData[chartID].dataZoom = null
dispatch(typePath.updateGridList, { chartID: chartID, length: 1 })
},
/**
* reset chart option
*
* @param {String} chartID
* @param {String} mappingID
* @param {String} cardName
*/
[typePath.resetSeriesData]: ({ state, getters, commit, dispatch }, payload) => {
const { chartID, mappingID } = payload
// check chart need to reset or not
if (String(mappingID) === String(state.chartData[chartID].mappingID)) {
// reset series data
for (const i in state.chartData[chartID].series) {
state.chartData[chartID].series[i].data.length = 0
}
// reset databuffer
const databuffer = dataStreamBuffer.getByChartID(chartID)
if (databuffer) {
for (const device in databuffer) {
// console.log('device', device)
for (const channel in databuffer[device]) {
// console.log('channel', channel, databuffer[device][channel])
databuffer[device][channel].length = 0
}
}
}
}
},
/**
* refresh (key++) EChart
*
*/
[typePath.refreshChart]: async ({ state, getters, commit, dispatch }, payload) => {
// to avoid overflow
state.taskContentChartKey < 1000 ? state.taskContentChartKey++ : state.taskContentChartKey = 0
},
/**
* refresh (key++) chart panel (i.e. EChart list)
*
*/
[typePath.refreshPanel]: async ({ state, getters, commit, dispatch }, payload) => {
// to avoid overflow
state.taskContentChartPanelKey < 1000 ? state.taskContentChartPanelKey++ : state.taskContentChartPanelKey = 0
},
[typePath.removeGridSource]: async ({ state, getters, commit, dispatch }, payload) => {
const { chartID, gridIndex, gridSourceIndex } = payload
const gridSource = state.chartData[chartID].gridSource[gridIndex][gridSourceIndex]
if (gridSource === undefined) return
// remove series
const seriesIndex = state.chartData[chartID].series.findIndex((val) => {
return val.name === gridSource.name
})
state.chartData[chartID].series.splice(seriesIndex, 1)
// remove legend
state.chartData[chartID].legend.data = state.chartData[chartID].legend.data.filter((val) => {
return val !== gridSource.name
})
// remove xAxis, yAxis seriesIndex
// state.chartData[chartID].xAxis[gridIndex].seriesIndex = state.chartData[chartID].xAxis[gridIndex].seriesIndex.filter((val) => {
// console.log(val, seriesIndex, val !== seriesIndex)
// return val !== seriesIndex
// })
// state.chartData[chartID].yAxis[gridIndex].seriesIndex = state.chartData[chartID].yAxis[gridIndex].seriesIndex.filter(ele => ele !== seriesIndex)
// remove gridsource
state.chartData[chartID].gridSource[gridIndex].splice(gridSourceIndex, 1)
state.chartData[chartID].gridSource = JSON.parse(JSON.stringify(state.chartData[chartID].gridSource))
checkMappingID(state.chartData[chartID])
},
[typePath.removeGrid]: async ({ state, getters, commit, dispatch }, payload) => {
const { chartID, gridIndex } = payload
// remove all grid source & series
if (state.chartData[chartID].gridSource[gridIndex]) {
for (const gridSource in state.chartData[chartID].gridSource[gridIndex]) {
await dispatch(typePath.removeGridSource, {
chartID: chartID,
gridIndex: gridIndex,
gridSourceIndex: gridSource,
})
}
}
state.chartData[chartID].xAxis.splice(gridIndex, 1)
state.chartData[chartID].yAxis.splice(gridIndex, 1)
state.chartData[chartID].grid.splice(gridIndex, 1)
console.log('removeGrid!!!!', state.chartData[chartID])
},
[typePath.reLegendName]: async ({ state, getters, commit, dispatch }, payload) => {
const { chartID } = payload
// remove all grid source & series
getLegendName(state.chartData[chartID].sourceList, null, state.deviceListNew)
},
}
export default chartActs
function checkMappingID (chart) {
// check id is need to remove or not
const idList = [...chart.mappingID]
for (const id of idList) {
const result = checkGridSource(chart, id)
if (result === false) {
chart.mappingID = chart.mappingID.filter(ele => ele !== id)
}
}
}
function checkGridSource (chart, deviceID) {
for (const grid of chart.grid) {
for (const gridSource of chart.gridSource[grid.index]) {
if (gridSource.xSource.mac_address === deviceID) {
return true
}
if (gridSource.ySource.mac_address === deviceID) {
return true
}
}
}
return false
}
function parseGridSourceAxis (gridSourceAxis) {
// gridsource axis example:
// 'X AXIS = TIME'
// 'Y AXIS = NEULIVE 0 CHANNEL 2'
const deviceInfo = {
deviceName: '',
deviceID: '',
channel: '',
}
if (gridSourceAxis.name === 'Time') {
deviceInfo.deviceName = 'Time'
deviceInfo.deviceID = 'Time'
deviceInfo.channel = 'Time'
} else {
deviceInfo.deviceName = gridSourceAxis.name
deviceInfo.deviceID = gridSourceAxis.id
deviceInfo.channel = Number(gridSourceAxis.channel)
deviceInfo.mac_address = gridSourceAxis.mac_address
}
// const eliteChannel = ['CURRENT', 'VOLTAGE', 'RESISTANCE']
// const parseResult = gridSourceAxis.split(' = ')[1].split(' ')
// const _deviceName = parseResult[0]
// if (_deviceName === 'TIME') {
// deviceInfo.deviceName = 'Time'
// deviceInfo.deviceID = 'Time'
// deviceInfo.channel = 'Time'
// } else {
// switch (_deviceName) {
// case 'NEULIVE':
// deviceInfo.deviceName = 'Neulive'
// deviceInfo.deviceID = parseResult[1]
// deviceInfo.channel = parseInt(parseResult[3])
// break
// case 'ELITE':
// deviceInfo.deviceName = 'Elite'
// deviceInfo.deviceID = parseResult[1]
// deviceInfo.channel = eliteChannel.indexOf(parseResult[2]) + 1
// break
// case 'ELITEEIS':
// deviceInfo.deviceName = 'EliteEIS'
// deviceInfo.deviceID = parseResult[1]
// deviceInfo.channel = Number(parseResult[3])
// break
// default:
// break
// }
// }
return deviceInfo
}
function getIndexArrayForBalenceSampleRate (indexArray, dis, l) {
if (indexArray.length >= 3 || dis <= 0) {
return indexArray
}
const per = dis / l
if (per >= 1) {
indexArray.push([1, Math.floor(per)])
dis = dis - (l * Math.floor(per))
} else {
indexArray.push([Math.ceil(1 / per), 1])
dis = dis - Math.floor(l / Math.ceil(1 / per))
}
return getIndexArrayForBalenceSampleRate(indexArray, dis, l)
}
// generate x axis format
function makeXAxis (gridIndex, type, channel) {
return {
type: type,
name: '',
gridIndex: gridIndex,
axisLine: { onZero: false, lineStyle: { color: '#aaa' } },
axisTick: { show: false },
axisLabel: {
show: true,
showMinLabel: false,
showMaxLabel: false,
color: '#34495e',
// rotate: 45,
// margin: 12,
},
splitLine: { show: true, lineStyle: { color: '#aaa' } },
// minorSplitLine: {
// show: true,
// lineStyle: { color: '#eee' },
// },
// splitNumber: 20,
interval: null,
scale: true,
min: 'dataMin',
max: 'dataMax',
channel: channel,
seriesIndex: [],
}
}
// generate y axis format
function makeYAxis (gridIndex, type, channel) {
return {
type: type,
// // name: 'none',
// // nameLocation: 'center',
// // nameTextStyle: {
// // // align: 'left',
// // // verticalAlign: 'bottom',
// // },
gridIndex: gridIndex,
axisTick: { show: false },
axisLine: { show: false }, // color: '#ccc' } },
axisLabel: {
show: true,
color: '#34495e',
showMinLabel: false,
showMaxLabel: false,
},
splitLine: { show: true, lineStyle: { color: '#aaa' } },
// // minorSplitLine: {
// // show: true,
// // lineStyle: { color: '#eee' },
// // },
animation: false,
scale: true,
min: 'dataMin',
max: 'dataMax',
splitNumber: 3,
// minInterval: 1,
interval: null,
channel: channel,
seriesIndex: [],
}
}
// generate grid
function makeGrid (index, length) {
const _height = (80 / length) + '%'
const _top = index * (80 / length) + 5 + '%'
return {
index: index,
top: _top,
height: _height,
left: '10%',
right: '4%',
series: [],
}
}
// get legend name
function getLegendName (sourceList, formulaID, deviceList) {
let legendName = ''
if (formulaID == null) {
// source only 2 device
sourceList.forEach(source => {
let device = ''
let channelName = ''
switch (source.name) {
case 'Time':
legendName += 'T'
break
case 'Elite':
// eslint-disable-next-line no-case-declarations
device = deviceList.find((ele) => String(ele.mac_address) === String(source.mac_address))
if (device === undefined) break
// eslint-disable-next-line no-case-declarations
channelName = getConfigChannel(device.library_name, device.configuration.MODE, source.channel - 1)
if (!channelName) break
legendName += source.mac_address.slice(12, 18) + '-' + channelName.name.replace('_', '')
break
case 'EliteEIS':
// eslint-disable-next-line no-case-declarations
device = deviceList.find((ele) => String(ele.mac_address) === String(source.mac_address))
if (device === undefined) break
// eslint-disable-next-line no-case-declarations
channelName = getConfigChannel(device.library_name, device.configuration.MODE, source.channel - 1)
if (!channelName) break
if ([0, 5].indexOf(Number(device.configuration.MODE)) !== -1) {
legendName += source.mac_address.slice(12, 18) + '-' + channelName.name.replace('_', '')
break
}
legendName += source.mac_address.slice(12, 18) + '-' + channelName.name.replace('_', '')
break
default:
legendName += 'D' + source.id + 'CH' + source.channel
break
}
legendName += '_'
})
legendName = legendName.substr(0, legendName.length - 1)
} else {
legendName = 'T_F' + formulaID
}
return legendName
}
function getConfigChannel (library, mode, channel) {
return config.getChannelConfig(library, mode, channel)
}
export function getTimeFormatter (val) {
const hour = parseInt(val / 3.6e9)
const minute = parseInt((val % 3.6e9) / 1000000 / 60)
const second = parseInt((val % 6e7) / 1000000)
const millisecond = parseInt((val % 1e6) / 1000)
let label = ''
if (hour > 0) {
label += hour + ' h '
}
if (minute > 0) {
label += minute + ' m '
}
if (second > 0) {
label += second + ' s '
}
if (millisecond > 0) {
label += millisecond + ' ms '
}
return label
}