import * as _ from 'lodash' ; import { Data } from '../../types' ; interface CheckerOption { edge : { autoLoop : boolean ; autoPoly : boolean ; } ; } function isEven ( number ) { return number % 2 === 0 ; } function isOdd ( number ) { return ! isEven ( number ) ; } function makePolyEdge ( edges , data , options ) { if ( ! options . edge . autoPoly ) return edges ; const noLoopEdges = edges . filter ( ( edge ) => edge . source !== edge . target ) ; const loopEdges = edges . filter ( ( edge ) => edge . source === edge . target ) ; const groups = _ . groupBy ( noLoopEdges , ( edge ) => { const name = [ edge . source , edge . target ] . sort ( ) ; return `${ name [ 0 ] }-${ name [ 1 ] }` ; } ) ; const polyGroups = _ . pickBy ( groups , ( group ) => group . length > 1 ) ; const directGroups = _ . pickBy ( groups , ( group ) => group . length <= 1 ) ; const polyEdges = _ . flatMap ( polyGroups , ( group ) => { let distance = isEven ( group . length ) ? - 20 : - 40 ; return group . map ( ( edge ) => { return { edge , point : [ edge . source , edge . target ] . sort ( ) , } ; } ) . map ( ( { edge , point } , index ) => { const source = data . nodes . find ( ( node ) => node . id === point [ 0 ] ) ; const target = data . nodes . find ( ( node ) => node . id === point [ 1 ] ) ; if ( ! source || ! target ) throw new Error ( 'Invalid Edge, Cannot Find Source/Target Node' ) ; if ( isEven ( group . length ) && isEven ( index ) ) distance += 40 ; if ( isOdd ( group . length ) && ( isOdd ( index ) || index === 0 ) ) distance += 40 ; const polyEdge = { ... edge , shape : 'PolyEdge' , } ; polyEdge . poly = { distance : isEven ( index ) ? distance : - distance , } ; return polyEdge ; } ) ; } ) ; const directEdges = _ . flatMap ( directGroups ) ; const transformedEdges = [ ... loopEdges , ... directEdges , ... polyEdges ] ; return transformedEdges ; } function checkEdges ( edges , data , options ) { let transformedEdges = edges . filter ( ( edge ) => { const { source , target } = edge ; if ( ! source || ! target ) { console . warn ( `edge requires  source and target，this '${ JSON . stringify ( edge ) }' edge will be automatically filtered` ) ; return false ; } if ( ! edge . data ) { console . warn ( `edge requires an data field，this '${ JSON . stringify ( edge ) }' edge will be automatically filtered` ) ; return false ; } /** 边是可以重复的，因为properties可能不一样 */ return true ; } ) . map ( ( edge ) => { const { shape , style } = edge ; return { type : shape || 'LineEdge' , style : style || { line : { width : 1 , } , label : { size : 12 , } , } , poly : { distance : 0 , } , loopCfg : { position : 'top' , dist : 20 , } , ... edge , data : { ... edge . data , source : edge . source , target : edge . target , } , } ; } ) . map ( ( edge ) => { if ( ! options . edge . autoLoop ) return edge ; if ( edge . type === 'LineEdge' && edge . source === edge . target ) { edge . type = 'loop' ; } return edge ; } ) ; transformedEdges = makePolyEdge ( transformedEdges , data , options ) ; return transformedEdges ; } function checkNodes ( nodes , _data , _options ) { const nodeIds = [ ] ; const graphinNodes = nodes . filter ( ( node ) => { const { id } = node ; if ( ! id ) { console . warn ( `node requires an id，this '${ JSON . stringify ( node ) }' node will be automatically filtered` ) ; return false ; } if ( ! node . data ) { console . warn ( `node requires an data field，this '${ JSON . stringify ( node ) }' node will be automatically filtered` ) ; return false ; } if ( nodeIds . indexOf ( id ) !== - 1 ) { return false ; } nodeIds . push ( id ) ; return true ; } ) . map ( ( node ) => { return { type : node . shape || 'CircleNode' , ... node , data : { ... node . data , id : node . id , } , } ; } ) ; return graphinNodes ; } const checkData = ( data = { nodes : [ ] , edges : [ ] } , options ) : Data => { const { edges = [ ] , nodes = [ ] , combos } = data ; const graphinNodes = checkNodes ( nodes , data , options ) ; const graphinEdges = checkEdges ( edges , data , options ) ; return { nodes : graphinNodes , edges : graphinEdges , combos , } ; } ; export default checkData ;