* Данные РТК вынесены в отдельный проп графика

* Добавлена прозрачность РТК
* Добавлен метод расчёта данных для РТК
This commit is contained in:
Александр Сироткин 2022-11-22 09:26:44 +05:00
parent a2d641abdd
commit 44afd5f1f0
4 changed files with 62 additions and 28 deletions

View File

@ -116,6 +116,8 @@ export type D3MonitoringChartsProps<DataType extends BaseDataType> = Omit<React.
loading?: boolean loading?: boolean
/** Массив отображаемых данных */ /** Массив отображаемых данных */
data?: DataType[] data?: DataType[]
/** Массив данных для прямоугольников */
flowData?: DataType[]
/** Отступы графика от края SVG */ /** Отступы графика от края SVG */
offset?: Partial<ChartOffset> offset?: Partial<ChartOffset>
/** Цвет фона в формате CSS-значения */ /** Цвет фона в формате CSS-значения */
@ -181,6 +183,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
loading = false, loading = false,
datasetGroups, datasetGroups,
data, data,
flowData,
plugins, plugins,
offset: _offset, offset: _offset,
yAxis: _yAxisConfig, yAxis: _yAxisConfig,
@ -493,7 +496,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
chartData = renderArea<DataType>(xAxis, yAxis, chart, chartData) chartData = renderArea<DataType>(xAxis, yAxis, chart, chartData)
break break
case 'rect_area': case 'rect_area':
renderRectArea<DataType>(xAxis, yAxis, chart) renderRectArea<DataType>(xAxis, yAxis, chart, flowData)
break break
default: default:
break break
@ -507,7 +510,7 @@ const _D3MonitoringCharts = <DataType extends Record<string, unknown>>({
chart.afterDraw?.(chart) chart.afterDraw?.(chart)
}) })
}) })
}, [data, groups, height, offset, sizes, chartDomains, yAxis]) }, [data, flowData, groups, height, offset, sizes, chartDomains, yAxis])
return ( return (
<LoaderPortal <LoaderPortal

View File

@ -6,7 +6,8 @@ import { appendTransition } from './base'
export const renderRectArea = <DataType extends BaseDataType>( export const renderRectArea = <DataType extends BaseDataType>(
xAxis: (value: d3.NumberValue) => number, xAxis: (value: d3.NumberValue) => number,
yAxis: (value: d3.NumberValue) => number, yAxis: (value: d3.NumberValue) => number,
chart: ChartRegistry<DataType> chart: ChartRegistry<DataType>,
data: DataType[] | undefined,
) => { ) => {
if ( if (
chart.type !== 'rect_area' || chart.type !== 'rect_area' ||
@ -14,25 +15,27 @@ export const renderRectArea = <DataType extends BaseDataType>(
!chart.maxXAccessor || !chart.maxXAccessor ||
!chart.minYAccessor || !chart.minYAccessor ||
!chart.maxYAccessor || !chart.maxYAccessor ||
!chart.data !data
) return ) return
const data = chart.data
const xMin = getByAccessor(chart.minXAccessor) const xMin = getByAccessor(chart.minXAccessor)
const xMax = getByAccessor(chart.maxXAccessor) const xMax = getByAccessor(chart.maxXAccessor)
const yMin = getByAccessor(chart.minYAccessor) const yMin = getByAccessor(chart.minYAccessor)
const yMax = getByAccessor(chart.maxYAccessor) const yMax = getByAccessor(chart.maxYAccessor)
chart().attr('fill', 'currentColor') chart()
.attr('fill', 'currentColor')
.attr('fill-opacity', '0.15')
.attr('stroke-opacity', '0.3')
const rects = chart().selectAll<SVGRectElement, null>('rect').data(data) const rects = chart().selectAll<SVGRectElement, null>('rect').data(data)
rects.exit().remove() rects.exit().remove()
rects.enter().append('rect') rects.enter().append('rect')
appendTransition(chart().selectAll<SVGRectElement, Record<string, any>>('rect'), chart) appendTransition(chart().selectAll<SVGRectElement, Record<string, any>>('rect'), chart)
.attr('x1', (d) => xAxis(xMin(d))) .attr('x', (d) => xAxis(xMin(d)))
.attr('x2', (d) => xAxis(xMax(d))) .attr('y', (d) => yAxis(yMin(d)))
.attr('y1', (d) => yAxis(yMin(d))) .attr('width', (d) => xAxis(xMax(d)) - xAxis(xMin(d)))
.attr('y2', (d) => yAxis(yMax(d))) .attr('height', (d) => yAxis(yMax(d)) - yAxis(yMin(d)))
} }

View File

@ -1,4 +1,4 @@
import { formatDate } from "@utils" import { formatDate } from '@utils'
export const yAxis = { export const yAxis = {
type: 'time', type: 'time',
@ -22,19 +22,46 @@ const makeDataset = (label, shortLabel, color, key, unit, other) => ({
...other, ...other,
}) })
export const makeChartGroups = (flowChart) => { const depthInBetween = (val, flow) => flow.depthStart <= val && val <= flow.depthEnd
export const calcFlowData = (dataSaub, flowChart) => {
if (dataSaub.length < 2) return []
let minDepth = Infinity, maxDepth = -Infinity
const dates = dataSaub.map((row) => {
const depth = row.wellDepth
if (depth < minDepth) minDepth = depth
if (depth > maxDepth) maxDepth = depth
return { date: new Date(row.date), depth: row.wellDepth }
})
const out = flowChart.map((flow) => {
if (flow.depthStart > maxDepth || flow.depthEnd < minDepth) return []
const out = []
let i = 0, j = 0
while (i < dates.length) {
while (i < dates.length && !depthInBetween(dates[i].depth, flow)) i++
j = i++
while (i < dates.length && depthInBetween(dates[i].depth, flow)) i++
if (j >= dates.length || j >= i)
break
out.push({
...flow,
dateStart: dates[j].date,
dateEnd: dates[i - 1].date,
})
}
return out
}).flat()
return out
}
export const makeChartGroups = () => {
const makeAreaOptions = (accessor) => ({ const makeAreaOptions = (accessor) => ({
type: 'rect_area', type: 'rect_area',
data: flowChart,
hideLabel: true, hideLabel: true,
yAxis: { minYAccessor: 'dateStart',
type: 'linear', maxYAccessor: 'dateEnd',
accessor: 'depth', minXAccessor: accessor + 'Min',
}, maxXAccessor: accessor + 'Max',
minXAccessor: 'depthStart',
maxXAccessor: 'depthEnd',
minYAccessor: accessor + 'Min',
maxYAccessor: accessor + 'Max',
linkedTo: accessor, linkedTo: accessor,
}) })

View File

@ -19,7 +19,7 @@ import {
TelemetryDataSpinService TelemetryDataSpinService
} from '@api' } from '@api'
import { makeChartGroups, yAxis } from './dataset' import { calcFlowData, makeChartGroups, yAxis } from './dataset'
import { ADDITIVE_PAGES, cutData, DATA_COUNT, getLoadingInterval, makeDateTimeDisabled } from './archive_methods' import { ADDITIVE_PAGES, cutData, DATA_COUNT, getLoadingInterval, makeDateTimeDisabled } from './archive_methods'
import ActiveMessagesOnline from './ActiveMessagesOnline' import ActiveMessagesOnline from './ActiveMessagesOnline'
import TelemetrySummary from './TelemetrySummary' import TelemetrySummary from './TelemetrySummary'
@ -94,8 +94,6 @@ const TelemetryView = memo(() => {
const onStatusChanged = useCallback((value) => updateWell({ idState: value }), [well]) const onStatusChanged = useCallback((value) => updateWell({ idState: value }), [well])
const dateTimeDisabled = useMemo(() => makeDateTimeDisabled(dateLimit, chartInterval), [dateLimit, chartInterval])
const handleDataSaub = useCallback((data, replace = false) => { const handleDataSaub = useCallback((data, replace = false) => {
setDataSaub((prev) => { setDataSaub((prev) => {
if (!data || !Array.isArray(data)) if (!data || !Array.isArray(data))
@ -137,6 +135,8 @@ const TelemetryView = memo(() => {
} }
}, [archiveMode, loadedDataRange, chartInterval, dateLimit]) }, [archiveMode, loadedDataRange, chartInterval, dateLimit])
const dateTimeDisabled = useMemo(() => makeDateTimeDisabled(dateLimit, chartInterval), [dateLimit, chartInterval])
const domain = useMemo(() => ({ min: new Date(+endDate - chartInterval), max: endDate }), [endDate, chartInterval]) const domain = useMemo(() => ({ min: new Date(+endDate - chartInterval), max: endDate }), [endDate, chartInterval])
const spinLast = useMemo(() => getLast(dataSpin), [dataSpin]) const spinLast = useMemo(() => getLast(dataSpin), [dataSpin])
@ -146,7 +146,9 @@ const TelemetryView = memo(() => {
const saubSubject$ = useMemo(() => new BehaviorSubject(), []) const saubSubject$ = useMemo(() => new BehaviorSubject(), [])
const spinSubject$ = useMemo(() => new BehaviorSubject(), []) const spinSubject$ = useMemo(() => new BehaviorSubject(), [])
const chartGroups = useMemo(() => makeChartGroups(flowChartData), [flowChartData]) const filteredData = useMemo(() => cutData(dataSaub, domain.min, domain.max), [dataSaub, domain])
const flowData = useMemo(() => calcFlowData(dataSaub, flowChartData), [dataSaub, flowChartData])
const chartGroups = useMemo(() => makeChartGroups(), [])
useEffect(() => { useEffect(() => {
if (!searchParams.has('range') || !searchParams.has('end')) return if (!searchParams.has('range') || !searchParams.has('end')) return
@ -253,8 +255,6 @@ const TelemetryView = memo(() => {
setEndDate(new Date(saubLast.date)) setEndDate(new Date(saubLast.date))
}, [archiveMode, saubLast]) }, [archiveMode, saubLast])
const filteredData = useMemo(() => cutData(dataSaub, domain.min, domain.max), [dataSaub, domain])
return ( return (
<LoaderPortal show={showLoader} style={{ flexGrow: 1 }}> <LoaderPortal show={showLoader} style={{ flexGrow: 1 }}>
<div className={'telemetry-view-page'}> <div className={'telemetry-view-page'}>
@ -312,6 +312,7 @@ const TelemetryView = memo(() => {
{...chartProps} {...chartProps}
yDomain={domain} yDomain={domain}
data={filteredData} data={filteredData}
flowData={flowData}
methods={setChartMethods} methods={setChartMethods}
datasetGroups={chartGroups} datasetGroups={chartGroups}
onWheel={onWheel} onWheel={onWheel}