diff --git a/concept/WellTelemetryAnalysis.jsx b/concept/WellTelemetryAnalysis.jsx deleted file mode 100755 index e0505b9..0000000 --- a/concept/WellTelemetryAnalysis.jsx +++ /dev/null @@ -1,163 +0,0 @@ -import { Table, Select, DatePicker } from "antd"; -import { TelemetryAnalyticsService } from "../src/services/api"; -import { useState, useEffect } from "react"; -import { useParams } from "react-router-dom"; -import notify from "../src/components/notify"; -import LoaderPortal from "../src/components/LoaderPortal"; -import moment from "moment"; -import "../styles/message.css"; - -const { Option } = Select; -const pageSize = 26; -const { RangePicker } = DatePicker; - -const columns = [ - { - title: "Название операции", - key: "name", - dataIndex: "name", - }, - { - title: "Дата начала операции", - key: "beginDate", - dataIndex: "beginDate", - render: (item) => moment.utc(item).local().format("DD MMM YYYY, HH:mm:ss"), - }, - { - title: "Дата окончания операции", - key: "endDate", - dataIndex: "endDate", - render: (item) => moment.utc(item).local().format("DD MMM YYYY, HH:mm:ss"), - }, - { - title: "Глубина скважины в начале операции", - key: "beginWellDepth", - dataIndex: "startWellDepth", - }, - { - title: "Глубина скважины в конце операции", - key: "endWellDepth", - dataIndex: "endWellDepth", - }, -]; - -const filterOptions = [ - { label: "Невозможно определить операцию", value: 1 }, - { label: "Роторное бурение", value: 2 }, - { label: "Слайдирование", value: 3 }, - { label: "Подъем с проработкой", value: 4 }, - { label: "Спуск с проработкой", value: 5 }, - { label: "Подъем с промывкой", value: 6 }, - { label: "Спуск с промывкой", value: 7 }, - { label: "Спуск в скважину", value: 8 }, - { label: "Спуск с вращением", value: 9 }, - { label: "Подъем из скважины", value: 10 }, - { label: "Подъем с вращением", value: 11 }, - { label: "Промывка в покое", value: 12 }, - { label: "Промывка с вращением", value: 13 }, - { label: "Удержание в клиньях", value: 14 }, - { label: "Неподвижное состояние", value: 15 }, - { label: "Вращение без циркуляции", value: 16 }, - { label: "На поверхности", value: 17 }, -]; - -export default function WellTelemetryAnalysis() { - let { id } = useParams(); - - const [page, setPage] = useState(1); - const [range, setRange] = useState([]); - const [categories, setCategories] = useState([]); - const [pagination, setPagination] = useState(null); - const [operations, setOperations] = useState([]); - - const [loader, setLoader] = useState(false); - - const children = filterOptions.map((line) => ( - - )); - - const onChangeRange = (range) => { - setRange(range); - }; - - useEffect(() => { - const GetOperations = async () => { - setLoader(true); - try { - let begin = null; - let end = null; - if (range?.length > 1) { - begin = range[0].toISOString(); - end = range[1].toISOString(); - } - - await TelemetryAnalyticsService.getOperationsByWell( - `${id}`, - (page - 1) * pageSize, - pageSize, - categories, - begin, - end - ).then((paginatedOperations) => { - setOperations( - paginatedOperations?.items.map((o) => { - return { - key: o.id, - begin: o.date, - ...o, - }; - }) - ); - - setPagination({ - total: paginatedOperations?.count, - current: Math.floor(paginatedOperations?.skip / pageSize), - }); - }); - } catch (ex) { - notify(`Не удалось загрузить операции по скважине "${id}"`, "error"); - console.log(ex); - } - setLoader(false); - }; - GetOperations(); - }, [id, categories, range, page]); - - return ( - <> -
-

Фильтр операций

- - -
- - setPage(page), - }} - rowKey={(record) => record.id} - /> - - - ); -} diff --git a/src/components/AnalysisOperationTime.jsx b/src/components/AnalysisOperationTime.jsx deleted file mode 100755 index 89a9209..0000000 --- a/src/components/AnalysisOperationTime.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import moment from 'moment' -import { DatePicker } from 'antd' -import { useState, useEffect } from 'react' -import { useParams } from 'react-router-dom' - -import LoaderPortal from '@components/LoaderPortal' -import { invokeWebApiWrapperAsync } from '@components/factory' -import { TelemetryAnalyticsService } from '@api' -import { ChartOperationTime } from './charts/ChartOperationTime' - -const { RangePicker } = DatePicker - -const lines = [{ labelAccessorName: 'processName', pieceAccessorName: 'duration' }] - -export const AnalysisOperationTime = () => { - const { id } = useParams() - const [operationTimeData, setOperationTimeData] = useState([]) - const [loader, setLoader] = useState(false) - const [range, setRange] = useState([moment().subtract(1,'days'), moment()]) - - useEffect(() => invokeWebApiWrapperAsync( - async () => { - const begin = range?.length > 1 ? range[0].toISOString() : null - const end = range?.length > 1 ? range[1].toISOString() : null - const summary = await TelemetryAnalyticsService.getOperationsSummary(id, begin, end) - setOperationTimeData(summary) - }, - setLoader, - `Не удалось получить данные для анализа Операция-Время по скважине '${id}' за период с ${begin} по ${end}`, - 'Получение данных для анализа Операция-Время по скважине' - ), [id, range]) - - return ( - - setRange(range)} /> - - - ) -} - -export default AnalysisOperationTime diff --git a/src/components/charts/ChartOperationTime.jsx b/src/components/charts/ChartOperationTime.jsx deleted file mode 100755 index 6de7784..0000000 --- a/src/components/charts/ChartOperationTime.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import moment from 'moment' -import { useEffect, useState } from 'react' - -import { ChartOpertationTimeBase } from './ChartOperationTimeBase' - -export const CreateLabels = () => { - let labels = [] - return labels -} - -export const CreateData = (lineConfig) => { - let datasets = { - label: lineConfig.label, - data: [], - backgroundColor: [ - '#f00', '#ff0', '#f0f', '#0ff', '#00f', '#0f0' - ], - } - return datasets -} - -export const ChartOperationTime = ({ lines, data, rangeDate }) => { - const [opertationTimeDataParams, setOpertationTimeDataParams] = useState({ data: { labels: [], datasets: [] } }) - - useEffect(() => { - if ((!lines) - || (!data)) - return - - let newLabels = lines.map(lineCfg => { - let labels = CreateLabels(lineCfg) - if (data.length !== 0) - labels = data.map(dataItem => { - return dataItem[lineCfg.labelAccessorName] - }) - return labels - }) - - let newDatasets = lines.map(lineCfg => { - let datasets = CreateData(lineCfg) - if (data.length !== 0) - datasets.data = data.map(dataItem => { - return dataItem[lineCfg.pieceAccessorName] - }) - return datasets - }) - - let interval = rangeDate ? (rangeDate[1] - rangeDate[0]) / 1000 : null - let startDate = rangeDate ? rangeDate[0] : moment() - let newParams = { - xInterval: interval, - xStart: startDate, - data: { - labels: newLabels, - datasets: newDatasets - } - } - setOpertationTimeDataParams(newParams) - - console.log(newParams) - - }, [data, lines, rangeDate]) - - return (<> - - - ) -} \ No newline at end of file diff --git a/src/components/charts/ChartOperationTimeBase.tsx b/src/components/charts/ChartOperationTimeBase.tsx deleted file mode 100755 index df48daf..0000000 --- a/src/components/charts/ChartOperationTimeBase.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import { useEffect, useRef, useState } from 'react' -import { - Chart, - ArcElement, - TimeScale, - Legend, - PointElement, - ChartData, - ChartTypeRegistry, - ChartOptions, - DoughnutController, -} from 'chart.js' -import 'chartjs-adapter-moment' -import ChartDataLabels from 'chartjs-plugin-datalabels' - -Chart.register(TimeScale, DoughnutController, PointElement, ArcElement, Legend, ChartDataLabels) - -const defaultOptions = { - responsive: true, - title: { - display: true, - position: 'top', - text: 'Doughnut Chart', - fontSize: 18, - fontColor: '#111' - }, - legend: { - display: true, - position: 'bottom', - labels: { - fontColor: '#333', - fontSize: 16 - } - } -} - -export type ChartTimeData = ChartData - -export type ChartTimeDataParams = { - data: ChartTimeData, - xStart?: Date, - xInterval?: number, - displayLabels?: Boolean, -} - -export type ChartTimeBaseProps = { - dataParams: ChartTimeDataParams, - // TODO: Create good type for options - options?: ChartOptions | 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 ChartOpertationTimeBase: React.FC = ({ options, dataParams }) => { - const chartRef = useRef(null) - const [chart, setChart] = useState() - - useEffect(() => { - if ((chartRef.current) && (!chart)) { - let thisOptions = {} - Object.assign(thisOptions, defaultOptions, options) - - let newChart = new Chart(chartRef.current, { - type: 'doughnut', - 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 () -} diff --git a/src/components/charts/ChartTelemetryDepthToDay.jsx b/src/components/charts/ChartTelemetryDepthToDay.jsx deleted file mode 100755 index e6c526e..0000000 --- a/src/components/charts/ChartTelemetryDepthToDay.jsx +++ /dev/null @@ -1,99 +0,0 @@ -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' - -Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement, Legend, ChartDataLabels, zoomPlugin) - -const defaultOptions = { - responsive: true, - aspectRatio: 2.45, - scales: { - x: { - type: 'time', - time: { - unit: 'hour', - displayFormats: { - hour: 'MM.DD' - }, - tooltipFormat: 'DD T' - }, - }, - y: { - type: 'linear', - position: 'top', - reverse: true, - // ticks: { - // // forces step size to be 50 units - // stepSize: 50 - // } - } - }, - parsing: { - xAxisKey: 'date', - yAxisKey: 'depth' - }, - elements: { - point: { - radius: 1.7, - hoverRadius: 5, - }, - }, - plugins: { - 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(() => { - const data = { - datasets: [ - makeDataset(depthData, 'Глубина', '#0A0'), - makeDataset(bitPositionData, 'Положение долота', 'blue'), - ] - } - - if(chartRef.current && !chart) { - const thisOptions = {} - Object.assign(thisOptions, defaultOptions) - - const 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() -} diff --git a/src/components/charts/ChartTelemetryDepthToInterval.jsx b/src/components/charts/ChartTelemetryDepthToInterval.jsx deleted file mode 100755 index d5995fc..0000000 --- a/src/components/charts/ChartTelemetryDepthToInterval.jsx +++ /dev/null @@ -1,74 +0,0 @@ -import { useEffect, useRef, useState } from 'react' -import { Chart, registerables } from 'chart.js' - -Chart.register(...registerables) - -const defaultOptions = { - responsive: true, - aspectRatio: 2.6, - scales: { - x: { - title: { - display: true, - text: 'Дата начала интервала' - }, - }, - y: { - title: { - display: true, - text: 'Коэффициент скорости' - } - } - }, - plugins: { - datalabels: { - display: false - } - } -} - -export const ChartTelemetryDepthToInterval = ({ depthToIntervalData }) => { - const chartRef = useRef(null) - const [chart, setChart] = useState() - - const calculateBarWidth = (dataLength) => { - if (dataLength < 3) return 150 - if (dataLength < 16) return 70 - return 10 - } - - useEffect(() => { - const xData = depthToIntervalData.map(el => new Date(el.intervalStartDate).toLocaleString()) - const yData = depthToIntervalData.map(el => el.intervalDepthProgress.toFixed(3)) - - const data = { - labels: xData, - datasets: [{ - label: 'Скорость проходки за интервал', - data: yData, - borderColor: '#00b300', - borderWidth: 2, - backgroundColor: '#0A0', - barThickness: calculateBarWidth(xData.length) - }] - } - - const thisOptions = {} - Object.assign(thisOptions, defaultOptions) - - if (chartRef.current && !chart) { - const newChart = new Chart(chartRef.current, { - type: 'bar', - options: thisOptions, - data: data - }) - setChart(newChart) - } else { - chart.data = data - chart.options = thisOptions - chart.update() - } - }, [chart, depthToIntervalData]) - - return () -} diff --git a/src/components/charts/ChartTelemetryOperationsSummary.jsx b/src/components/charts/ChartTelemetryOperationsSummary.jsx deleted file mode 100755 index 7228cea..0000000 --- a/src/components/charts/ChartTelemetryOperationsSummary.jsx +++ /dev/null @@ -1,89 +0,0 @@ -import { useEffect, useRef, useState } from 'react' -import { Chart, registerables } from 'chart.js' - -Chart.register(...registerables) - -const transformSecondsToHoursString = (seconds) => { - const hours = Math.floor(seconds / 3600) - const minutes = Math.floor((seconds % 3600) / 60) - const s = seconds - (hours * 3600) - (minutes * 60) - - return `${hours} ч.${minutes} мин.${s} сек.` -} - -const transformSecondsToTimeString = (seconds) => { - if (seconds === 1) // 1 is default state if null returned (1 is to show chart anyway with 0 sec) - return '0 сек.' - else if(seconds < 60) - return seconds + ' сек.' - else if (seconds < 3600) - return Math.floor(seconds / 60) + ' мин. ' + (0.6 * (seconds % 60)).toFixed() + ' сек.' - else - return transformSecondsToHoursString(seconds) -} - -const defaultOptions = { - responsive: true, - aspectRatio: 2.8, - plugins: { - datalabels: { - color: '#ffffff', - formatter: transformSecondsToTimeString, - font: { - weight: 'bold' - } - }, - tooltip: { - callbacks: { - label: (tooltipItem) => transformSecondsToTimeString(tooltipItem.parsed), - } - } - } -} - -const chartPartsColors = [ - '#54a60c', '#0ca68a', '#0c8aa6', '#0c57a6', '#0c33a6', - '#6f10d5', '#d510a1', '#f1bc41', '#c5f141', '#41f196', - '#41cbf1', '#4196f1', '#bf41f1', '#41f1c5', '#cbf141', - '#f1ce41', '#f17f41', '#f14141', '#34b40e', '#420eb4' -] - -export const ChartTelemetryOperationsSummary = ({ operationsData }) => { - const chartRef = useRef(null) - const [chart, setChart] = useState() - - useEffect(() => { - const namesData = operationsData?.map(el => el.operationName) ?? ['Нет операций'] - const durationsData = operationsData?.map(el => el.duration) ?? [1] - - const data = { - labels: namesData, - datasets: [ - { - label: 'Скорость проходки за интервал', - data: durationsData, - borderColor: chartPartsColors, - backgroundColor: chartPartsColors, - } - ] - } - - const thisOptions = {} - Object.assign(thisOptions, defaultOptions) - - if (chartRef.current && !chart) { - const newChart = new Chart(chartRef.current, { - type: 'doughnut', - options: thisOptions, - data: data - }) - setChart(newChart) - } else { - chart.data = data - chart.options = thisOptions - chart.update() - } - }, [chart, operationsData]) - - return () -} diff --git a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToDay.jsx b/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToDay.jsx deleted file mode 100755 index b2f3c6e..0000000 --- a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToDay.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import { useState, useEffect, memo, useContext } from 'react' - -import { IdWellContext } from '@asb/context' -import LoaderPortal from '@components/LoaderPortal' -import { invokeWebApiWrapperAsync } from '@components/factory' -import { ChartTelemetryDepthToDay } from '@components/charts/ChartTelemetryDepthToDay' -import { TelemetryAnalyticsService } from '@api' - - -export const TelemetryAnalysisDepthToDay = memo(() => { - const [depthData, setDepthData] = useState([]) - const [bitPositionData, setBitPositionData] = useState([]) - const [loader, setLoader] = useState(false) - - const idWell = useContext(IdWellContext) - - useEffect(() => invokeWebApiWrapperAsync( - async () => { - const depthToDayData = await TelemetryAnalyticsService.getWellDepthToDay(idWell) - - const depths = depthToDayData.map(el => ({depth: el.wellDepth, date: el.date})) - .sort((a, b) => new Date(a.date) - new Date(b.date)) - setDepthData(depths) - - const bitPositions = depthToDayData.map(el => ({depth: el.bitDepth, date: el.date})) - .sort((a, b) => new Date(a.date) - new Date(b.date)) - setBitPositionData(bitPositions) - }, - setLoader, - `Не удалось получить данные для анализа Глубина-День по скважине "${idWell}"`, - 'Получение данных для анализа Глубина-День' - ), [idWell]) - - return ( - -
- -
-
- ) -}) - -export default TelemetryAnalysisDepthToDay diff --git a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToInterval.jsx b/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToInterval.jsx deleted file mode 100755 index f2a6f6c..0000000 --- a/src/pages/TelemetryAnalysis/TelemetryAnalysisDepthToInterval.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { Select } from 'antd' -import { useState, useEffect, memo, useContext } from 'react' - -import { IdWellContext } from '@asb/context' -import LoaderPortal from '@components/LoaderPortal' -import { invokeWebApiWrapperAsync } from '@components/factory' -import { ChartTelemetryDepthToInterval } from '@components/charts/ChartTelemetryDepthToInterval' -import { TelemetryAnalyticsService } from '@api' -import { arrayOrDefault } from '@utils' - - -const timePeriodCollection = [ - { value: '3600', label: '1 час' }, - { value: '21600', label: '6 часов' }, - { value: '43200', label: '12 часов' }, - { value: '86400', label: '24 часа' } -] - -export const TelemetryAnalysisDepthToInterval = memo(() => { - const [depthToIntervalData, setDepthToIntervalData] = useState([]) - const [chartInterval, setChartInterval] = useState(86400) - const [loader, setLoader] = useState(false) - - const idWell = useContext(IdWellContext) - - useEffect(() => invokeWebApiWrapperAsync( - async () => { - const depthToIntervalData = await TelemetryAnalyticsService.getWellDepthToInterval(idWell, chartInterval) - setDepthToIntervalData(arrayOrDefault(depthToIntervalData)) - }, - setLoader, - `Не удалось получить данные для анализа скорость проходки-интервал "${idWell}"`, - 'Получение данных для анализа скорость проходки-интервал' - ), [idWell, chartInterval]) - - return ( - -
-