import { DataStream , DataStreamId , Primitive } from '../../../../utils/dataTypes' ; import { getBreachedThreshold } from './utils' ; import { isDefined } from '../../../../utils/predicates' ; import { Threshold } from '../types' ; import { closestPoint } from '../../sc-webgl-base-chart/activePoints' ; import { StreamType } from '../../../../utils/dataConstants' ; import { DATA_ALIGNMENT } from '../constants' ; const isHigherPriority = ( t1 , t2 ) : Threshold => { if ( t1 == null ) { return t2 ; } if ( t1 . severity == null && t2 . severity == null ) { return t1 ; } if ( t1 . severity == null ) { return t2 ; } if ( t2 . severity == null ) { return t1 ; } return t1 . severity <= t2 . severity ? t1 : t2 ; } ; /**
 * Returns the most important threshold.
 *
 * The most important threshold is the visual which is most important to a user
 * This is determined via the `severity`. Lower severity means highest importance.
 *
 * If no thresholds are present with `severity`, the first threshold is returned.
 */ export const highestPriorityThreshold = ( thresholds ) : Threshold | undefined => { return thresholds . reduce ( isHigherPriority , undefined ) ; } ; /**
 * returns whether the given threshold can be applied to the requested data stream.
 *
 * EXPOSED FOR TESTING
 */ export const thresholdAppliesToDataStream = ( threshold , dataStreamId ) : boolean => { const { dataStreamIds } = threshold ; if ( dataStreamIds == null ) { return true ; } return dataStreamIds . includes ( dataStreamId ) ; } ; /**
 * Returns all of the breached thresholds for any of the alarms associated with the requested data stream.
 *
 * Does NOT return them in any sort of priority order.
 *
 * EXPOSED FOR TESTING
 */ export const breachedAlarmThresholds = ( { date , dataStream , dataStreams , thresholds , } ) : Threshold [ ] => { const alarmStreamIds = dataStream . associatedStreams != null ? dataStream . associatedStreams . filter ( ( { type } ) => type === StreamType . ALARM ) . map ( ( { id } ) => id ) : [ ] ; const isAssociatedAlarm = ( stream ) => alarmStreamIds . includes ( stream . id ) ; const alarmStreams = dataStreams . filter ( isAssociatedAlarm ) ; const allBreachedAlarmThresholds = alarmStreams . map ( stream => { const alarmThresholds = thresholds . filter ( threshold => thresholdAppliesToDataStream ( threshold , stream . id ) ) ; const latestAlarmValue = closestPoint ( stream . data , date , DATA_ALIGNMENT . LEFT ) ; return latestAlarmValue != null ? getBreachedThreshold ( latestAlarmValue . y , alarmThresholds ) : undefined ; } ) . filter ( isDefined ) ; return allBreachedAlarmThresholds ; } ; /**
 * Get the highest priority breached threshold.
 *
 * NOTE: If you do not want to get alarm thresholds, simply pass in an empty array for the `dataStreams`.
 */ export const breachedThreshold = ( { value , date , thresholds , dataStreams , dataStream , } ) : Threshold | undefined => { const applicableThresholds = thresholds . filter ( threshold => thresholdAppliesToDataStream ( threshold , dataStream . id ) ) ; const dataThreshold = value != null ? getBreachedThreshold ( value , applicableThresholds ) : undefined ; const alarmThresholds = breachedAlarmThresholds ( { date , dataStream , dataStreams , thresholds , } ) ; return highestPriorityThreshold ( [ dataThreshold , ... alarmThresholds ] . filter ( isDefined ) ) ; } ;