import { Table as RawTable, Typography } from 'antd' import { Fragment, memo, useCallback, useContext, useEffect, useState } from 'react' import { IdWellContext } from '@asb/context' import LoaderPortal from '@components/LoaderPortal' import { invokeWebApiWrapperAsync } from '@components/factory' import { WellSelector } from '@components/selectors/WellSelector' import { makeGroupColumn, makeNumericColumn, makeNumericRender, makeTextColumn, Table } from '@components/Table' import { OperationStatService, WellOperationService } from '@api' import { arrayOrDefault } from '@utils' import '@styles/index.css' import '@styles/statistics.less' const { Text } = Typography const { Summary } = RawTable const { Cell, Row } = Summary const numericRender = makeNumericRender() const speedNumericRender = (section) => numericRender(section?.speed) const makeSectionSorter = (key, name) => (a, b) => (a?.[key]?.[name] ?? 0) - (b?.[key]?.[name] ?? 0) export const makeSectionColumn = (title, key, { speedRender } = {}) => makeGroupColumn(title, [ makeNumericColumn('Проходка', key, null, null, (section => numericRender(section?.depth)), 100, { sorter: makeSectionSorter(key, 'depth'), }), makeNumericColumn('Время', key, null, null, (section => numericRender(section?.time)), 100, { sorter: makeSectionSorter(key, 'time'), }), makeNumericColumn((<>Vрейсовая), key, null, null, speedRender ?? speedNumericRender, 100, { sorter: makeSectionSorter(key, 'speed'), }), ]) export const defaultColumns = [ //makeTextColumn('Куст', 'cluster', null, null, null, { fixed: 'left', width: 100 }), makeTextColumn('Скважина', 'caption', null, null, null, { fixed: 'left', width: 100 }), ] const scrollSettings = { scrollToFirstRowOnChange: true, x: 100, y: 200 } const summaryColSpan = 1 /// TODO: Когда добавится куст изменить на 2 const getWellData = async (wellsList) => { const stats = arrayOrDefault(await OperationStatService.getWellsStat(wellsList)) const wellData = stats.map((well) => { const stat = { // cluster: null, caption: well.caption, } well.sections?.forEach(({ id, fact }) => { if (!fact) return stat[`section_${id}`] = { time: (+new Date(fact.end) - +new Date(fact.start)) / 3600_000, depth: fact.wellDepthEnd - fact.wellDepthStart, speed: fact.routeSpeed, } }) return stat }) return wellData } export const Statistics = memo(() => { const [sectionTypes, setSectionTypes] = useState([]) const [avgColumns, setAvgColumns] = useState(defaultColumns) const [cmpColumns, setCmpColumns] = useState(defaultColumns) const [isAvgTableLoading, setIsAvgTableLoading] = useState(false) const [isCmpTableLoading, setIsCmpTableLoading] = useState(false) const [isPageLoading, setIsPageLoading] = useState(false) const [avgWells, setAvgWells] = useState([]) const [cmpWells, setCmpWells] = useState([]) const [avgData, setAvgData] = useState([]) const [cmpData, setCmpData] = useState([]) const [avgRow, setAvgRow] = useState({}) const idWell = useContext(IdWellContext) const cmpSpeedRender = useCallback((key) => (section) => { let spanClass = '' // Дополнительная проверка на "null" необходима, чтобы значение "0" не стало исключением if ((avgRow[key]?.speed ?? null) !== null && (section?.speed ?? null) !== null) { const avgSpeed = avgRow[key].speed - section.speed if (avgSpeed < 0) spanClass = 'high-efficienty' else if (avgSpeed > 0) spanClass = 'low-efficienty' } return ( {numericRender(section?.speed)} ) }, [avgRow]) useEffect(() => invokeWebApiWrapperAsync( async () => { const types = await WellOperationService.getSectionTypes(idWell) setSectionTypes(Object.entries(types)) }, setIsPageLoading, `Не удалось получить типы секции`, `Получение списка возможных секций`, ), [idWell]) useEffect(() => invokeWebApiWrapperAsync( async () => { const filteredSections = avgData?.length > 0 ? sectionTypes.filter(([id, _]) => avgData.some((row) => `section_${id}` in row)) : sectionTypes setAvgColumns([ ...defaultColumns, ...filteredSections.map(([id, name]) => makeSectionColumn(name, `section_${id}`)), ]) setCmpColumns([ ...defaultColumns, ...filteredSections.map(([id, name]) => makeSectionColumn(name, `section_${id}`, { speedRender: cmpSpeedRender(`section_${id}`) })) ]) }, setIsPageLoading, 'Не удалось установить необходимые столбцы' ), [sectionTypes, avgData, cmpSpeedRender]) useEffect(() => invokeWebApiWrapperAsync( async () => { const avgData = await getWellData(avgWells) setAvgData(avgData) const avgRow = {} avgData.forEach((row) => row && Object.keys(row).forEach((key) => { if (!key.startsWith('section_')) return if (!avgRow[key]) avgRow[key] = { depth: 0, time: 0, speed: 0, count: 0 } avgRow[key].depth += row[key].depth ?? 0 avgRow[key].time += row[key].time ?? 0 avgRow[key].speed += row[key].speed ?? 0 avgRow[key].count++ })) Object.values(avgRow).forEach((section) => section.speed /= section.count) setAvgRow(avgRow) }, setIsAvgTableLoading, 'Не удалось загрузить данные для расчёта средних значений', ), [avgWells]) useEffect(() => invokeWebApiWrapperAsync( async () => { const cmpData = await getWellData(cmpWells) setCmpData(cmpData) }, setIsCmpTableLoading, 'Не удалось получить скважины для сравнения', ), [cmpWells]) const getStatisticsAvgSummary = useCallback((data) => ( Итого: {sectionTypes.map(([id, _], i) => ( {numericRender(avgRow[`section_${id}`]?.depth)} {numericRender(avgRow[`section_${id}`]?.time)} {numericRender(avgRow[`section_${id}`]?.speed)} ))} ), [avgRow, sectionTypes]) return (

Расчёт средних значений без Цифровой буровой

Выберите скважины для расчёта средних значений:
Выберите скважины сравнения:
) }) export default Statistics