forked from ddrilling/asb_cloud_front
Fixed Telemetry depth to day chart
This commit is contained in:
parent
eab4e3d749
commit
2855adefd7
@ -17,18 +17,6 @@ Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement
|
||||
const defaultOptions = {
|
||||
responsive: true,
|
||||
aspectRatio: 2.6,
|
||||
//maintainAspectRatio: false,
|
||||
//animation: false,
|
||||
// tooltips: {
|
||||
// enabled: true,
|
||||
// callbacks: {
|
||||
// label(tooltipItem) {
|
||||
// return tooltipItem.yLabel;
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
//events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
|
||||
|
||||
interaction: {
|
||||
intersect: false,
|
||||
mode: 'index',
|
||||
@ -42,7 +30,6 @@ const defaultOptions = {
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'hour',
|
||||
|
||||
displayFormats: {
|
||||
'hour': 'MM.DD'
|
||||
}
|
||||
@ -51,7 +38,6 @@ const defaultOptions = {
|
||||
drawTicks: true,
|
||||
},
|
||||
ticks: {
|
||||
//count:24,
|
||||
stepSize:3,
|
||||
major:{enabled:true,},
|
||||
z: 1,
|
||||
@ -137,7 +123,7 @@ export default function ChartDepthToDay({dataPlan, dataFact, dataForecast}) {
|
||||
setChart(newChart)
|
||||
|
||||
return () => chart?.destroy()
|
||||
}else{
|
||||
} else {
|
||||
chart.data = data
|
||||
chart.update()
|
||||
}
|
||||
|
@ -1,37 +1,121 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { ChartTelemetryDepthToDayBase } from './ChartTelemetryDepthToDayBase'
|
||||
import { CreateDataset } from './ChartTimeArchive'
|
||||
import {useEffect, useRef, useState} from 'react';
|
||||
import {
|
||||
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}) => {
|
||||
const [depthToDayDataParams, setDepthToDayDataParams] = useState({data: {datasets: []}})
|
||||
Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin);
|
||||
|
||||
useEffect(() => {
|
||||
if (!lines || !data)
|
||||
return
|
||||
|
||||
let newDatasets = lines.map(lineCfg => {
|
||||
let datasets = CreateDataset(lineCfg)
|
||||
if(data.length !== 0)
|
||||
datasets.data = data.map(dataItem => {
|
||||
return {
|
||||
x: new Date(dataItem[lineCfg.xAccessorName??'date']),
|
||||
y: dataItem[lineCfg.yAccessorName],
|
||||
label: dataItem[lineCfg.label]
|
||||
}
|
||||
})
|
||||
return datasets
|
||||
})
|
||||
|
||||
let newParams = {
|
||||
displayLabels: true,
|
||||
data: {
|
||||
datasets: newDatasets
|
||||
const defaultOptions = {
|
||||
responsive: true,
|
||||
aspectRatio: 2.6,
|
||||
interaction: {
|
||||
intersect: false,
|
||||
mode: 'index',
|
||||
},
|
||||
scales: {
|
||||
x:{
|
||||
display: true,
|
||||
title: {
|
||||
display: true
|
||||
},
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'hour',
|
||||
displayFormats: {
|
||||
'hour': 'MM.DD'
|
||||
}
|
||||
},
|
||||
grid:{
|
||||
drawTicks: true,
|
||||
},
|
||||
ticks: {
|
||||
z: 1,
|
||||
display : true,
|
||||
textStrokeColor : "#fff",
|
||||
textStrokeWidth : 2,
|
||||
color:"#000",
|
||||
}
|
||||
}
|
||||
setDepthToDayDataParams(newParams)
|
||||
}, [data, lines])
|
||||
},
|
||||
|
||||
return (
|
||||
<ChartTelemetryDepthToDayBase dataParams={depthToDayDataParams} />
|
||||
)
|
||||
y:{
|
||||
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} />)
|
||||
}
|
@ -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} />)
|
||||
}
|
@ -4,13 +4,9 @@ import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||
import { TelemetryAnalyticsService } from "../../services/api"
|
||||
import LoaderPortal from '../../components/LoaderPortal'
|
||||
|
||||
const lines = [
|
||||
{ label: "Глубина забоя", yAccessorName: "wellDepth", color: '#f00' },
|
||||
{ label: "Положение инструмента", yAccessorName: "bitDepth", color: '#ff0' }
|
||||
]
|
||||
|
||||
export default function TelemetryAnalysisDepthToDay({idWell}) {
|
||||
const [depthToDayData, setDepthToDayData] = useState([])
|
||||
const [depthData, setDepthData] = useState([])
|
||||
const [bitPositionData, setBitPositionData] = useState([])
|
||||
const [loader, setLoader] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
@ -18,7 +14,12 @@ export default function TelemetryAnalysisDepthToDay({idWell}) {
|
||||
invokeWebApiWrapperAsync(
|
||||
async () => {
|
||||
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,
|
||||
`Не удалось получить данные для Анализа Глубина-День по скважине "${idWell}"`)
|
||||
@ -27,8 +28,8 @@ export default function TelemetryAnalysisDepthToDay({idWell}) {
|
||||
return (
|
||||
<LoaderPortal show={loader}>
|
||||
<ChartTelemetryDepthToDay
|
||||
data={depthToDayData}
|
||||
lines={lines}
|
||||
depthData={depthData}
|
||||
bitPositionData={bitPositionData}
|
||||
/>
|
||||
</LoaderPortal>
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user