import { MappedTopic , MappedTopicsMap } from '@/services/data/pipeline/pipeline-relations' ; import { Pipeline } from '@/services/data/tuples/pipeline-types' ; import { Topic , TopicId } from '@/services/data/tuples/topic-types' ; import { isRawTopic } from '@/services/data/tuples/topic-utils' ; import { getCurrentTheme } from '@/widgets/theme/theme-wrapper' ; import { DQCMaps , DQCRelations } from '../../cache/types' ; import { getPipelineName , getTopicName } from '../../utils' ; interface Link { source : Topic ; target : Topic ; size : number ; pipeline : Pipeline ; } const findTopic = ( topicsMap , idOrName ? ) : Topic | undefined => { if ( idOrName ) { let topic = topicsMap [ idOrName ] ; if ( ! topic ) { topic = Object . values ( topicsMap ) . find ( ( { topic } ) => topic . name === idOrName ) ; } return topic ? topic . topic : ( void 0 ) ; } return ( void 0 ) ; } ; const buildLinks = ( options ) => { const { source , processedTopics , relations , links , stops } = options ; processedTopics . push ( source ) ; const topicRelation = relations . topics [ source . topicId ] ; topicRelation . trigger . forEach ( pipeline => { const pipelineRelation = relations . pipelines [ pipeline . pipelineId ] ; pipelineRelation . outgoing . forEach ( ( { topic : target , factors } ) => { if ( processedTopics . includes ( target ) ) { return ; } links . push ( { source , target , size : factors . length || 1 , pipeline } ) ; if ( target === stops ) { processedTopics . push ( target ) ; return ; } buildLinks ( { source : target , processedTopics , relations , links , stops } ) ; } ) ; } ) ; } ; const filterByTargets = ( links , targets ) => { const linkMap = links . reduce ( ( map , link ) => { const topicId = link . target . topicId ; let exists = map [ topicId ] ; if ( ! exists ) { exists = [ ] ; map [ topicId ] = exists ; } exists . push ( link ) ; return map ; } , { } as Record < string , Array < Link > > ) ; const pickedLinks = [ ] ; const findLinksToTargets = ( targets ) => { return targets . map < Array < Link > > ( target => linkMap [ target . topicId ] ) . filter ( x => ! ! x ) . flat ( ) ; } ; let linksToTargets = findLinksToTargets ( targets ) ; while ( linksToTargets . length !== 0 ) { linksToTargets . forEach ( link => { if ( ! pickedLinks . includes ( link ) ) { pickedLinks . push ( link ) ; } } ) ; linksToTargets = findLinksToTargets ( linksToTargets . map ( link => link . source ) ) ; } return pickedLinks ; } ; export const compute = ( options ) => { const { starts , stops , maps , relations } = options ; const startTopic = findTopic ( maps . topics , starts ) ; const stopTopic = findTopic ( maps . topics , stops ) ; let processedTopics = [ ] ; let links = [ ] ; Object . values ( maps . topics ) . filter ( ( { topic } ) => { return ( ! startTopic && isRawTopic ( topic ) ) || topic === startTopic ; } ) . forEach ( ( { topic } ) => { buildLinks ( { source : topic , processedTopics , relations , links , stops : stopTopic } ) ; } ) ; if ( stopTopic ) { links = filterByTargets ( links , [ stopTopic ] ) ; } const existsMap = links . reduce ( ( map , { source , target } ) => { map [ source . topicId ] = source ; map [ target . topicId ] = target ; return map ; } , { } as Record < TopicId , Topic > ) ; processedTopics = processedTopics . filter ( topic => ! ! existsMap [ topic . topicId ] ) ; if ( ! processedTopics || processedTopics . length === 0 ) { return ( void 0 ) ; } const theme = getCurrentTheme ( ) ; return { tooltip : { trigger : 'item' , triggerOn : 'mousemove' , formatter : ( { data : { name , source , target , value , pipeline } } ) => { if ( name ) { return `<span style="font-variant: petite-caps;font-weight: bold;color:var(--info-color)">${ name }</span>` ; } else { return '<div style="display:grid;grid-template-columns:auto 1fr;grid-column-gap:var(--margin)">' + [ [ 'From' , source ] , [ 'To' , target ] , [ 'Through' , pipeline ] , [ 'Touched Factors' , value ] ] . map ( x => { return `<span style="font-variant:petite-caps;font-family:var(--title-font-family);color:var(--info-color)">${ x [ 0 ] }:</span>` + `<span style="font-family:var(--title-font-family)">${ x [ 1 ] }</span>` ; } ) . join ( '' ) + '</div>' ; } } } , animation : true , series : [ { type : 'sankey' , emphasis : { focus : 'adjacency' } , nodeAlign : 'right' , data : processedTopics . map ( ( topic ) => { return { name : getTopicName ( topic ) } ; } ) , links : links . map ( ( { source , target , size , pipeline } ) => { return { source : getTopicName ( source ) , target : getTopicName ( target ) , value : size , pipeline : getPipelineName ( pipeline ) } ; } ) , label : { color : theme . fontColor , textBorderColor : theme . bgColor , textBorderWidth : 1 } , lineStyle : { color : 'source' } } ] } ; } ;