From 1dd19399e599745791984c9d8f8c923cd8723626 Mon Sep 17 00:00:00 2001 From: goodmice Date: Mon, 22 Aug 2022 14:47:14 +0500 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=20=D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8?= =?UTF-8?q?=D1=87=D0=B5=D1=81=D0=BA=D0=BE=D0=B5=20=D0=BC=D0=B0=D1=81=D1=88?= =?UTF-8?q?=D1=82=D0=B0=D0=B1=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B4=D0=BB=D1=8F=20TVD=20=D0=B8=20=D0=9E=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Telemetry/Operations/index.jsx | 11 ++- src/pages/WellOperations/Tvd/index.jsx | 99 ++++++++++++++++-------- src/utils/functions/numbers.tsx | 9 +++ 3 files changed, 86 insertions(+), 33 deletions(-) diff --git a/src/pages/Telemetry/Operations/index.jsx b/src/pages/Telemetry/Operations/index.jsx index c518806..282c1db 100644 --- a/src/pages/Telemetry/Operations/index.jsx +++ b/src/pages/Telemetry/Operations/index.jsx @@ -6,7 +6,7 @@ import { useWell } from '@asb/context' import LoaderPortal from '@components/LoaderPortal' import { DateRangeWrapper } from '@components/Table' import { invokeWebApiWrapperAsync } from '@components/factory' -import { getPermissions, arrayOrDefault, range, wrapPrivateComponent } from '@utils' +import { getPermissions, arrayOrDefault, range, wrapPrivateComponent, pretify } from '@utils' import { DetectedOperationService, DrillerService, TelemetryDataSaubService } from '@api' import DrillerList from './DrillerList' @@ -16,6 +16,7 @@ import OperationsChart from './OperationsChart' import OperationsTable from './OperationsTable' import '@styles/detected_operations.less' +import { unique } from '@asb/utils/filters' const Operations = memo(() => { const [isLoading, setIsLoading] = useState(false) @@ -61,6 +62,14 @@ const Operations = memo(() => { { actionName: 'Получение списка определённых операций', well } ), [well, dates, selectedCategory]) + useEffect(() => { + if (!data?.operations) return + const maxTarget = Math.max(...data.operations?.map((op) => op.operationValue?.targetValue || 0)) + const uniqueOps = data.operations?.map((op) => op.value || 0).filter(unique) + const value = uniqueOps.reduce((out, op) => out + op, 0) / uniqueOps.length * 3 / 2 + setYDomain(pretify(Math.max(maxTarget, value))) + }, [data]) + useEffect(() => { if (permissions.driller.get) updateDrillers() diff --git a/src/pages/WellOperations/Tvd/index.jsx b/src/pages/WellOperations/Tvd/index.jsx index 8bfed7c..f295d49 100644 --- a/src/pages/WellOperations/Tvd/index.jsx +++ b/src/pages/WellOperations/Tvd/index.jsx @@ -8,7 +8,7 @@ import { useWell } from '@asb/context' import { D3Chart } from '@components/d3' import LoaderPortal from '@components/LoaderPortal' import { invokeWebApiWrapperAsync } from '@components/factory' -import { formatDate, fractionalSum, wrapPrivateComponent, getOperations } from '@utils' +import { formatDate, fractionalSum, wrapPrivateComponent, getOperations, pretify } from '@utils' import TLPie from './TLPie' import TLChart from './TLChart' @@ -21,10 +21,26 @@ import '@styles/index.css' import '@styles/tvd.less' const operationsColors = [ - '#1abc9c', '#16a085', '#2ecc71', '#27ae60', '#3498db', - '#2980b9', '#9b59b6', '#8e44ad', '#34495e', '#2c3e50', - '#f1c40f', '#f39c12', '#e67e22', '#d35400', '#e74c3c', - '#c0392b', '#ecf0f1', '#bdc3c7', '#95a5a6', '#7f8c8d', + '#1abc9c', + '#16a085', + '#2ecc71', + '#27ae60', + '#3498db', + '#2980b9', + '#9b59b6', + '#8e44ad', + '#34495e', + '#2c3e50', + '#f1c40f', + '#f39c12', + '#e67e22', + '#d35400', + '#e74c3c', + '#c0392b', + '#ecf0f1', + '#bdc3c7', + '#95a5a6', + '#7f8c8d', ] export const makeGetColor = (types) => (type) => { @@ -35,14 +51,17 @@ export const makeGetColor = (types) => (type) => { return i < 0 ? operationsColors[type] : operationsColors[i] } -const Item = ({ label, children, ...other }) => (
{label}: {children}
) +const Item = ({ label, children, ...other }) => ( +
+ {label}: + {children} +
+) -const numericRender = (d) => d && Number.isFinite(+d) ? (+d).toFixed(2) : '-' +const numericRender = (d) => (d && Number.isFinite(+d) ? (+d).toFixed(2) : '-') const tooltipRender = (data) => { - if (!data || data.length <= 0) return ( - Данных нет - ) + if (!data || data.length <= 0) return Данных нет return data.map(({ chart, data }) => { const xFormat = (d) => chart.xAxis.format?.(d) ?? `${numericRender(d)} ${chart.xAxis.unit ?? ''}` @@ -57,19 +76,23 @@ const tooltipRender = (data) => { {data.slice(0, 2).map((d, i) => { const text = `${xFormat(chart.x(d))} :: ${yFormat(chart.y(d))}` - const href = ['plan', 'fact'].includes(chart.key) && `/well/${d.idWell}/operations/${chart.key}/?selectedId=${d.id}` + const href = + ['plan', 'fact'].includes(chart.key) && + `/well/${d.idWell}/operations/${chart.key}/?selectedId=${d.id}` return (
{href ? ( - + {text} ) : ( - - {text} - + {text} )}
) @@ -89,7 +112,7 @@ const xAxis = { type: 'linear', accessor: 'day', unit: 'день', - } + }, } const ticks = { @@ -105,27 +128,17 @@ const ticks = { x: { visible: true, count: d3.timeDay.every(1), - format: (d, i) => i % 2 === 0 ? formatDate(d, undefined, 'YYYY-MM-DD') : '', + format: (d, i) => (i % 2 === 0 ? formatDate(d, undefined, 'YYYY-MM-DD') : ''), }, y: { visible: true }, - } -} - -const domain = { - date: { - y: { min: 4500, max: 0 }, }, - day: { - x: { min: 0 }, - y: { min: 4500, max: 0 }, - } } const plugins = { tooltip: { enabled: true, limit: 3, height: 200, render: tooltipRender }, menu: { enabled: false }, legend: { enabled: true, offset: { x: 400 }, type: 'horizontal' }, - cursor: { enabled: false } + cursor: { enabled: false }, } const makeDataset = (key, label, color, width, radius, dash) => ({ @@ -146,7 +159,7 @@ const makeDataset = (key, label, color, width, radius, dash) => ({ fillOpacity: 0.1, shape: 'vline', strokeWidth: 1.5, - radius + radius, }, }) @@ -174,7 +187,26 @@ const Tvd = memo(({ well: givenWell, title, ...other }) => { return { ...operations, withoutNpt } }, [operations]) - + + const domain = useMemo(() => { + const maxValue = Math.max( + ...Object.entries(chartData) + .map(([_, ops]) => Math.max(...ops.map((op) => op.depth).filter(Boolean))) + .filter(Boolean) + ) + const minValue = pretify(maxValue) + + return { + date: { + y: { min: minValue, max: 0 }, + }, + day: { + x: { min: 0 }, + y: { min: minValue, max: 0 }, + }, + } + }, [chartData]) + const datasets = useMemo(() => { const radius = pointsEnabled ? 6 : 1 @@ -202,7 +234,10 @@ const Tvd = memo(({ well: givenWell, title, ...other }) => {

{title || 'График Глубина-день'}

{ }) export default wrapPrivateComponent(Tvd, { - requirements: [ 'OperationStat.get', 'DetectedOperation.get' ], + requirements: ['OperationStat.get', 'DetectedOperation.get'], title: 'TVD', route: 'tvd', }) diff --git a/src/utils/functions/numbers.tsx b/src/utils/functions/numbers.tsx index 6e6ca26..4de2a13 100644 --- a/src/utils/functions/numbers.tsx +++ b/src/utils/functions/numbers.tsx @@ -25,6 +25,15 @@ export const limitValue = (min: T, max: T) => (value: T) => { */ export const range = (end: number, start: number = 0) => Array.from({ length: end - start }, (_, i) => start + i) +export const pretify = (n: number): number | null => { + if (!Number.isFinite(n)) return null + let i = 0 + for (; Math.abs(n) >= 100; i++) n /= 10 + const sign = Math.sign(n), nn = Math.floor(n / 10) + n = (Math.abs(n) % 10 < 5) ? nn * 10 + sign * 5 : (nn + sign) * 10 + return n * Math.pow(10, i) +} + export type DisplayValueOptions = { def?: ReactNode inf?: ReactNode | ((v: number) => ReactNode)