Fixed Telemetry depth to day chart

This commit is contained in:
KharchenkoVV 2021-09-09 11:13:32 +05:00
parent eab4e3d749
commit 2855adefd7
4 changed files with 126 additions and 280 deletions

View File

@ -17,18 +17,6 @@ Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement
const defaultOptions = { const defaultOptions = {
responsive: true, responsive: true,
aspectRatio: 2.6, aspectRatio: 2.6,
//maintainAspectRatio: false,
//animation: false,
// tooltips: {
// enabled: true,
// callbacks: {
// label(tooltipItem) {
// return tooltipItem.yLabel;
// }
// }
// },
//events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
interaction: { interaction: {
intersect: false, intersect: false,
mode: 'index', mode: 'index',
@ -42,7 +30,6 @@ const defaultOptions = {
type: 'time', type: 'time',
time: { time: {
unit: 'hour', unit: 'hour',
displayFormats: { displayFormats: {
'hour': 'MM.DD' 'hour': 'MM.DD'
} }
@ -51,7 +38,6 @@ const defaultOptions = {
drawTicks: true, drawTicks: true,
}, },
ticks: { ticks: {
//count:24,
stepSize:3, stepSize:3,
major:{enabled:true,}, major:{enabled:true,},
z: 1, z: 1,
@ -137,7 +123,7 @@ export default function ChartDepthToDay({dataPlan, dataFact, dataForecast}) {
setChart(newChart) setChart(newChart)
return () => chart?.destroy() return () => chart?.destroy()
}else{ } else {
chart.data = data chart.data = data
chart.update() chart.update()
} }

View File

@ -1,37 +1,121 @@
import { useEffect, useState } from 'react' import {useEffect, useRef, useState} from 'react';
import { ChartTelemetryDepthToDayBase } from './ChartTelemetryDepthToDayBase' import {
import { CreateDataset } from './ChartTimeArchive' Chart,
TimeScale,
LinearScale,
Legend,
LineController,
PointElement,
LineElement
} from 'chart.js'
import 'chartjs-adapter-moment';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import zoomPlugin from 'chartjs-plugin-zoom';
export const ChartTelemetryDepthToDay = ({data, lines}) => { Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin);
const [depthToDayDataParams, setDepthToDayDataParams] = useState({data: {datasets: []}})
useEffect(() => { const defaultOptions = {
if (!lines || !data) responsive: true,
return aspectRatio: 2.6,
interaction: {
let newDatasets = lines.map(lineCfg => { intersect: false,
let datasets = CreateDataset(lineCfg) mode: 'index',
if(data.length !== 0) },
datasets.data = data.map(dataItem => { scales: {
return { x:{
x: new Date(dataItem[lineCfg.xAccessorName??'date']), display: true,
y: dataItem[lineCfg.yAccessorName], title: {
label: dataItem[lineCfg.label] display: true
} },
}) type: 'time',
return datasets time: {
}) unit: 'hour',
displayFormats: {
let newParams = { 'hour': 'MM.DD'
displayLabels: true, }
data: { },
datasets: newDatasets grid:{
drawTicks: true,
},
ticks: {
z: 1,
display : true,
textStrokeColor : "#fff",
textStrokeWidth : 2,
color:"#000",
} }
} },
setDepthToDayDataParams(newParams)
}, [data, lines])
return ( y:{
<ChartTelemetryDepthToDayBase dataParams={depthToDayDataParams} /> type:'linear',
) position:'top',
reverse:true,
display: true,
title: {
display: false,
text: ''
},
}
},
parsing: {
xAxisKey: 'date',
yAxisKey: 'depth'
},
elements:{
point:{
radius:1.7,
hoverRadius:5,
},
},
plugins:{
legend:{
display: true,
},
datalabels: {
display: false,
},
}
}
const makeDataset = (data, label, color, width=1.5, dash) => ({
label: label,
data: data,
backgroundColor: color,
borderColor: color,
borderWidth: width,
borderDash: dash,
})
export const ChartTelemetryDepthToDay = ({depthData, bitPositionData}) => {
const chartRef = useRef(null)
const [chart, setChart] = useState()
useEffect(() => {
let data = {
datasets: [
makeDataset(depthData, 'Глубина', '#0A0'),
makeDataset(bitPositionData, 'Положение долота', 'blue')
]
}
if((chartRef.current)&&(!chart)) {
let thisOptions = {}
Object.assign(thisOptions, defaultOptions)
let newChart = new Chart(chartRef.current, {
type: 'line',
plugins: [ChartDataLabels],
options: thisOptions,
data: data
})
setChart(newChart)
return () => chart?.destroy()
} else {
chart.data = data
chart.update()
}
}, [chart, depthData, bitPositionData])
return(<canvas ref={chartRef} />)
} }

View File

@ -1,225 +0,0 @@
import {useEffect, useRef, useState} from 'react';
import {
Chart,
TimeScale,
LinearScale,
Legend,
LineController,
PointElement,
LineElement,
ChartData,
ChartTypeRegistry,
ChartOptions
} from 'chart.js'
import 'chartjs-adapter-moment';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import zoomPlugin from 'chartjs-plugin-zoom';
Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin);
const defaultOptions = {
responsive: true,
aspectRatio: 6,
animation: false,
tooltips: {
enabled: true,
callbacks: {
label(tooltipItem:any) {
return tooltipItem.yLabel;
}
}
},
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
scales: {
x:{
type: 'time',
reverse: false,
time: {
stepSize: 20,
displayFormats: {
millisecond: 'HH:mm:ss.SSS',
second: 'HH:mm:ss',
minute: 'HH:mm:ss',
hour: 'DD HH:mm:ss',
day: 'MM.DD HH:mm',
week: 'yy.MM.DD HH:mm',
month: 'yyyy.MM.DD',
quarter: 'yyyy.MM.DD',
year: 'yyyy.MM',
},
},
grid:{
drawTicks: false,
},
ticks: {
z: 1,
display : true,
textStrokeColor : "#fff",
textStrokeWidth : 2,
color:"#000",
}
},
y:{
type:'linear',
position:'top',
reverse: true,
}
},
elements:{
point:{
radius:0,
hoverRadius:5,
},
},
plugins:{
legend:{
display: true,
},
datalabels: {
display: false,
},
}
}
export type ChartTimeData = ChartData<keyof ChartTypeRegistry, {
x: Date;
label: number;
y: number;
}[], unknown>
export type ChartTimeDataParams = {
data: ChartTimeData,
xStart?: Date,
xInterval?: number,
displayLabels?: Boolean,
}
export type ChartTimeBaseProps = {
dataParams: ChartTimeDataParams,
// TODO: Create good type for options
options?: ChartOptions<keyof ChartTypeRegistry> | any,
}
export type TimeParams = {
unit: String
stepSize: number
}
const linesPerInterval = 32
export const timeUnitByInterval = (intervalSec:number):String => {
if(intervalSec <= 60)
return 'millisecond'
if(intervalSec <= 32*60)
return 'second'
if(intervalSec <= 32*60*60)
return 'minute'
if(intervalSec <= 32*12*60*60)
return 'hour'
if(intervalSec <= 32*24*60*60)
return 'day'
if(intervalSec <= 32*7*24*60*60)
return 'week'
if(intervalSec <= 32*30.4375*24*60*60)
return 'month'
if(intervalSec <= 32*121.75*24*60*60)
return 'quarter'
else
return 'year'
}
export const timeParamsByInterval = (intervalSec:number) :TimeParams => {
let stepSize = intervalSec
let unit = timeUnitByInterval(intervalSec)
switch(unit){
case "millisecond":
stepSize *= 1000
break;
case "second":
//stepSize *= 1
break;
case "minute":
stepSize /= 60
break;
case "hour":
stepSize /= 60*60
break;
case "day":
stepSize /= 24*60*60
break;
case "week":
stepSize /= 7*24*60*60
break;
case "month":
stepSize /= 30*24*60*60
break;
case "quarter":
stepSize /= 91*24*60*60
break;
case "year":
stepSize /= 365.25*24*60*60
break;
}
stepSize = Math.round(stepSize/linesPerInterval)
stepSize = stepSize > 0 ? stepSize : 1;
return {unit, stepSize}
}
export const ChartTelemetryDepthToDayBase: React.FC<ChartTimeBaseProps> = ({options, dataParams}) => {
const chartRef = useRef<HTMLCanvasElement>(null)
const [chart, setChart] = useState<any>()
useEffect(() => {
if((chartRef.current)&&(!chart)) {
let thisOptions = {}
Object.assign(thisOptions, defaultOptions, options)
let newChart = new Chart(chartRef.current, {
type: 'line',
plugins: [ChartDataLabels],
options: thisOptions,
data: dataParams.data
})
setChart(newChart)
return () => chart?.destroy()
}
}, [chart, options, dataParams])
useEffect(() => {
if (!chart)
return
chart.data = dataParams.data
chart.options.aspectRatio = options?.aspectRatio
if (dataParams.xStart) {
let interval = Number(dataParams.xInterval ?? 600)
let start = new Date(dataParams.xStart)
let end = new Date(dataParams.xStart)
end.setSeconds(end.getSeconds() + interval)
let {unit, stepSize} = timeParamsByInterval(interval)
if(chart.options.scales?.x){
chart.options.scales.x.max = end.getTime()
chart.options.scales.x.min = start.getTime()
chart.options.scales.x.ticks.display = dataParams.displayLabels ?? true
chart.options.scales.x.time.unit = unit
chart.options.scales.x.time.stepSize = stepSize
}
}
chart.update()
}, [chart, dataParams, options])
return(<canvas ref={chartRef} />)
}

View File

@ -4,13 +4,9 @@ import { invokeWebApiWrapperAsync } from '../../components/factory'
import { TelemetryAnalyticsService } from "../../services/api" import { TelemetryAnalyticsService } from "../../services/api"
import LoaderPortal from '../../components/LoaderPortal' import LoaderPortal from '../../components/LoaderPortal'
const lines = [
{ label: "Глубина забоя", yAccessorName: "wellDepth", color: '#f00' },
{ label: "Положение инструмента", yAccessorName: "bitDepth", color: '#ff0' }
]
export default function TelemetryAnalysisDepthToDay({idWell}) { export default function TelemetryAnalysisDepthToDay({idWell}) {
const [depthToDayData, setDepthToDayData] = useState([]) const [depthData, setDepthData] = useState([])
const [bitPositionData, setBitPositionData] = useState([])
const [loader, setLoader] = useState(false) const [loader, setLoader] = useState(false)
useEffect(() => { useEffect(() => {
@ -18,7 +14,12 @@ export default function TelemetryAnalysisDepthToDay({idWell}) {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const depthToDayData = await TelemetryAnalyticsService.getWellDepthToDay(idWell) const depthToDayData = await TelemetryAnalyticsService.getWellDepthToDay(idWell)
setDepthToDayData(depthToDayData)
const depths = depthToDayData.map(el => ({depth: el.wellDepth, date: el.date}))
setDepthData(depths)
const bitPositions = depthToDayData.map(el => ({depth: el.bitDepth, date: el.date}))
setBitPositionData(bitPositions)
}, },
setLoader, setLoader,
`Не удалось получить данные для Анализа Глубина-День по скважине "${idWell}"`) `Не удалось получить данные для Анализа Глубина-День по скважине "${idWell}"`)
@ -27,8 +28,8 @@ export default function TelemetryAnalysisDepthToDay({idWell}) {
return ( return (
<LoaderPortal show={loader}> <LoaderPortal show={loader}>
<ChartTelemetryDepthToDay <ChartTelemetryDepthToDay
data={depthToDayData} depthData={depthData}
lines={lines} bitPositionData={bitPositionData}
/> />
</LoaderPortal> </LoaderPortal>
) )