|
|
|
|
@ -1,13 +1,5 @@
|
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
import type {
|
|
|
|
|
DeviceTimelineRow,
|
|
|
|
|
HourlyStatusItem,
|
|
|
|
|
OverviewOption,
|
|
|
|
|
RunOverviewData,
|
|
|
|
|
RunOverviewMetric,
|
|
|
|
|
RunOverviewQueryParams,
|
|
|
|
|
RunStatus
|
|
|
|
|
} from './components/types'
|
|
|
|
|
import type { DeviceTimelineRow, OverviewOption, RunOverviewData, RunOverviewQueryParams, RunStatus } from './components/types'
|
|
|
|
|
|
|
|
|
|
const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'
|
|
|
|
|
|
|
|
|
|
@ -81,93 +73,13 @@ const toTimelineRows = (deviceOptions: OverviewOption[]): DeviceTimelineRow[] =>
|
|
|
|
|
segments: shiftTimeline(BASE_SEGMENTS, TIMELINE_OFFSETS[index % TIMELINE_OFFSETS.length])
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
const toHourlyStatus = (summaryFactor: number): HourlyStatusItem[] =>
|
|
|
|
|
Array.from({ length: 24 }, (_, hour) => {
|
|
|
|
|
const runningBase = 74 + Math.sin((hour / 24) * Math.PI * 3) * 14 + summaryFactor * 2
|
|
|
|
|
const standbyBase = 10 + Math.cos((hour / 24) * Math.PI * 4) * 7
|
|
|
|
|
const faultBase = 2 + Math.max(0, Math.sin((hour - 5) / 2.2)) * 5
|
|
|
|
|
|
|
|
|
|
const running = Math.max(48, Math.min(88, Number(runningBase.toFixed(2))))
|
|
|
|
|
const standby = Math.max(4, Math.min(26, Number(standbyBase.toFixed(2))))
|
|
|
|
|
const fault = Math.max(1, Math.min(8, Number(faultBase.toFixed(2))))
|
|
|
|
|
const offline = Number(Math.max(4, 100 - running - standby - fault).toFixed(2))
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
hour: `${String(hour).padStart(2, '0')}:00`,
|
|
|
|
|
running,
|
|
|
|
|
standby,
|
|
|
|
|
fault,
|
|
|
|
|
offline
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const createMetrics = (summaryFactor: number): RunOverviewMetric[] => [
|
|
|
|
|
{
|
|
|
|
|
key: 'utilizationRate',
|
|
|
|
|
icon: 'ep:pie-chart',
|
|
|
|
|
value: Number((75.42 + summaryFactor * 1.2).toFixed(2)),
|
|
|
|
|
unit: '%',
|
|
|
|
|
change: 4.32
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'powerOnRate',
|
|
|
|
|
icon: 'ep:video-play',
|
|
|
|
|
value: Number((90.12 + summaryFactor * 0.7).toFixed(2)),
|
|
|
|
|
unit: '%',
|
|
|
|
|
change: 2.15
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'faultRate',
|
|
|
|
|
icon: 'ep:warning',
|
|
|
|
|
value: Number(Math.max(1.5, 3.21 - summaryFactor * 0.35).toFixed(2)),
|
|
|
|
|
unit: '%',
|
|
|
|
|
change: -1.03
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'standbyRate',
|
|
|
|
|
icon: 'ep:timer',
|
|
|
|
|
value: Number(Math.max(4, 6.67 - summaryFactor * 0.25).toFixed(2)),
|
|
|
|
|
unit: '%',
|
|
|
|
|
change: -1.14
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const createSummary = (summaryFactor: number) => {
|
|
|
|
|
const running = Number((75.42 + summaryFactor * 1.2).toFixed(2))
|
|
|
|
|
const standby = Number(Math.max(4, 6.67 - summaryFactor * 0.25).toFixed(2))
|
|
|
|
|
const fault = Number(Math.max(1.5, 3.21 - summaryFactor * 0.35).toFixed(2))
|
|
|
|
|
const offline = Number((100 - running - standby - fault).toFixed(2))
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
{ status: 'running' as const, percent: running, hours: Number(((24 * running) / 100).toFixed(2)) },
|
|
|
|
|
{ status: 'standby' as const, percent: standby, hours: Number(((24 * standby) / 100).toFixed(2)) },
|
|
|
|
|
{ status: 'fault' as const, percent: fault, hours: Number(((24 * fault) / 100).toFixed(2)) },
|
|
|
|
|
{ status: 'offline' as const, percent: offline, hours: Number(((24 * offline) / 100).toFixed(2)) }
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const buildRunOverviewData = (
|
|
|
|
|
export const buildRunOverviewTimelineData = (
|
|
|
|
|
query: RunOverviewQueryParams,
|
|
|
|
|
deviceOptions: OverviewOption[] = FALLBACK_DEVICE_OPTIONS
|
|
|
|
|
): RunOverviewData => {
|
|
|
|
|
const summaryFactor =
|
|
|
|
|
query.quickRange === 'today'
|
|
|
|
|
? 0
|
|
|
|
|
: query.quickRange === 'yesterday'
|
|
|
|
|
? -0.8
|
|
|
|
|
: query.quickRange === 'last7Days'
|
|
|
|
|
? 1.1
|
|
|
|
|
: query.quickRange === 'last30Days'
|
|
|
|
|
? 0.45
|
|
|
|
|
: 0.15
|
|
|
|
|
|
|
|
|
|
): Pick<RunOverviewData, 'timelineRows' | 'totalDevices'> => {
|
|
|
|
|
const rows = toTimelineRows(deviceOptions.length > 0 ? deviceOptions : FALLBACK_DEVICE_OPTIONS)
|
|
|
|
|
const filteredRows = query.deviceId.length > 0 ? rows.filter((row) => query.deviceId.includes(row.id)) : rows
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
metrics: createMetrics(summaryFactor),
|
|
|
|
|
hourlyStatus: toHourlyStatus(summaryFactor),
|
|
|
|
|
summary: createSummary(summaryFactor),
|
|
|
|
|
timelineRows: filteredRows,
|
|
|
|
|
totalDevices: filteredRows.length
|
|
|
|
|
}
|
|
|
|
|
|