diff --git a/src/components/Main.js b/src/components/Main.js index b2d1a99a..ed489bf5 100644 --- a/src/components/Main.js +++ b/src/components/Main.js @@ -9,7 +9,6 @@ import Composition from './views/compositions/Composition'; import GenericMechanism from './views/mechanisms/GenericMechanism'; import MetaDiagram, { ComponentsMap } from "@metacell/meta-diagram"; import CustomLinkWidget from './views/projections/CustomLinkWidget'; - const mockModel = require('../resources/model').mockModel; const styles = () => ({ @@ -26,24 +25,22 @@ class Main extends React.Component { constructor (props) { super(props); this.state = {}; + this.interpreter = new ModelInterpreter(mockModel); + this.model = this.interpreter.getModel(); + this.metaModel = this.interpreter.getMetaModel(); + this.componentsMap = new ComponentsMap(new Map(), new Map()); + + this.componentsMap.nodes.set(PNLClasses.COMPOSITION, Composition); + this.componentsMap.nodes.set(PNLClasses.MECHANISM, GenericMechanism); + this.componentsMap.links.set(PNLClasses.PROJECTION, CustomLinkWidget); } render() { const { classes } = this.props; - const interpreter = new ModelInterpreter(mockModel); - const model = interpreter.getModel(); - const metaModel = buildModel(model); - console.log(interpreter.getModelElementsMap()) - - const componentsMap = new ComponentsMap(new Map(), new Map()); - - componentsMap.nodes.set(PNLClasses.COMPOSITION, Composition); - componentsMap.nodes.set(PNLClasses.MECHANISM, GenericMechanism); - componentsMap.links.set(PNLClasses.PROJECTION, CustomLinkWidget); return (
- ); default: - console.log('different port found' + port.getName() + ' ' + port.getType()); + // TODO: what to do with other ports? + // console.log('different port found' + port.getName() + ' ' + port.getType()); } })} diff --git a/src/model/Interpreter.ts b/src/model/Interpreter.ts index 81e46b8e..b2c7857e 100644 --- a/src/model/Interpreter.ts +++ b/src/model/Interpreter.ts @@ -1,46 +1,51 @@ -import { GVTypes, PNLClasses } from '../constants'; -import { PortTypes } from '@metacell/meta-diagram'; +import { PNLClasses } from '../constants'; +import { MetaLink, MetaNode, PortTypes } from '@metacell/meta-diagram'; import ProjectionLink from './links/ProjectionLink'; import QueryService from '../services/queryService'; import MechanismNode from './nodes/mechanism/MechanismNode'; import CompositionNode from './nodes/composition/CompositionNode'; -const typesArray = Object.values(GVTypes); -const parse = require('dotparser'); - - export default class ModelInterpreter { nativeModel: any; jsonModel: Object; modelMap: { [key: string]: Map }; + pnlModel: { [key: string]: Array }; + metaModel: { [key: string]: Array }; + nodeIdsMap: Map; + linkIdsMap: Map; constructor(model: any) { this.modelMap = { 'nodes': new Map(), 'links': new Map() }; + this.pnlModel = { + [PNLClasses.COMPOSITION]: [], + [PNLClasses.MECHANISM]: [], + [PNLClasses.PROJECTION]: [], + }; + this.metaModel = { + [PNLClasses.COMPOSITION]: [], + [PNLClasses.MECHANISM]: [], + [PNLClasses.PROJECTION]: [], + }; + this.nodeIdsMap = new Map(); + this.linkIdsMap = new Map(); this.nativeModel = model; this.jsonModel = this._convertModel(model); } _convertModel(model: any) : Object { - const parsedModel = { - [PNLClasses.COMPOSITION]: [], - [PNLClasses.MECHANISM]: [], - }; - - parsedModel[PNLClasses.COMPOSITION] = model[PNLClasses.COMPOSITION].map((singleModel: any) => { - const newModel = parse(singleModel).map((elem: any) => this.castObject(elem, undefined, this.modelMap)); - return newModel; + model[PNLClasses.COMPOSITION].forEach((singleModel: any) => { + this.nodeIdsMap = new Map(); + this.linkIdsMap = new Map(); + this.castComposition(singleModel, undefined, this.modelMap); }); - - parsedModel[PNLClasses.MECHANISM] = model[PNLClasses.MECHANISM].map((singleNode: any) => { - let tempNode = parse(singleNode)[0].children.filter((elem: { node_id: { id: string; }; }) => elem.node_id.id !== 'graph'); - let newNode = tempNode.map((elem: any) => this.castObject(elem, undefined, this.modelMap)); - return newNode; + model[PNLClasses.MECHANISM].forEach((singleNode: any) => { + this.castMechanism(singleNode, undefined, this.modelMap); }); - - return parsedModel; + this.setMetaModel() + return this.pnlModel; } updateModel(newModel: any) { @@ -51,6 +56,22 @@ export default class ModelInterpreter { return this.jsonModel; } + setMetaModel() { + this.metaModel[PNLClasses.COMPOSITION] = this.pnlModel[PNLClasses.COMPOSITION].map( + (item:CompositionNode) => item.getMetaNode() + ); + this.metaModel[PNLClasses.MECHANISM] = this.pnlModel[PNLClasses.MECHANISM].map( + (item:MechanismNode) => item.getMetaNode() + ); + this.metaModel[PNLClasses.PROJECTION] = this.pnlModel[PNLClasses.PROJECTION].map( + (item:ProjectionLink) => item.getMetaLink() + ); + } + + getMetaModel() { + return this.metaModel; + } + getNativeModel() { return this.nativeModel; } @@ -88,99 +109,166 @@ export default class ModelInterpreter { return ports; } - castObject( + castComposition( item: MechanismNode|CompositionNode|ProjectionLink|any, parent: any|undefined, modelMap: { [key: string]: Map }) - : MechanismNode|CompositionNode|ProjectionLink { + : MechanismNode|CompositionNode|ProjectionLink { let newNode = item; - if (item?.type === undefined) { - throw new TypeError('type is missing, object cannot be casted to the right class type.'); + let extra: { [key: string]: any } = {}; + let ports : any = []; + let boundingBox = { + llx: 0, + lly: 0, + urx: 0, + ury: 0, + }; + if (item?.bb) { + let _vertices = item.bb.split(','); + boundingBox.llx = _vertices[0]; + boundingBox.lly = _vertices[1]; + boundingBox.urx = _vertices[2]; + boundingBox.ury = _vertices[3]; } - switch (item.type) { - case GVTypes.COMPOSITION: { - let extra: { [key: string]: any } = {}; - let ports : any = []; - let children: { [key: string]: any } = { - [PNLClasses.MECHANISM]: [], - [PNLClasses.PROJECTION]: [], - [PNLClasses.COMPOSITION]: [], - } - newNode = new CompositionNode(item.id, parent, '', false, ports, extra, children); - modelMap['nodes'].set(newNode.getName(), newNode); - item.children.forEach((element: any) => { - if (element.type === 'attr_stmt') { - extra[element.target] = {} - element.attr_list.forEach( (innerElement: any) => { - if (innerElement.type === 'attr') { - extra[element.target][innerElement?.id] = innerElement?.eq; - } - }); - return; - } - if (typesArray.includes(element.type)) { - switch (element.type) { - case GVTypes.COMPOSITION: { - children[PNLClasses.COMPOSITION].push(this.castObject(element, newNode, modelMap)); - break; - } - case GVTypes.MECHANISM: { - children[PNLClasses.MECHANISM].push(this.castObject(element, newNode, modelMap)); - break; - } - case GVTypes.PROJECTION: { - children[PNLClasses.PROJECTION].push(this.castObject(element, newNode, modelMap)); - break; - } - default: - // TODO: enable this in the future - // throw new Error(`Casting error, "${item.type}" type not known.`); - console.log(`Casting error, "${item.type}" type not known.`); - } - } - }); - break; + newNode = new CompositionNode(item?.name, parent, '', false, ports, extra, undefined, boundingBox); + modelMap['nodes'].set(newNode.getName(), newNode); + // temp array to host all the nested compositions + let childrenCompositions: Array = []; + + // we iterate the objects and first identify all the mechanisms + item.objects.forEach((child: any) => { + let newChild = undefined; + if (child.rankdir) { + // we park for now nested compositions + childrenCompositions.push(child) + } else { + newChild = this.castMechanism(child, newNode, this.modelMap); + newNode.addChild(newChild); } - case GVTypes.MECHANISM: { - let ports: { [key: string]: any } = this.parseNodePorts(item?.node_id?.id, PNLClasses.MECHANISM); - let extra: { [key: string]: any } = {}; - item.attr_list.forEach((singleAttr: any) => { - if (singleAttr.type === 'attr') { - extra[singleAttr?.id] = singleAttr?.eq; - } - }); - newNode = new MechanismNode(item?.node_id?.id, parent, '', false, ports, extra); - modelMap['nodes'].set(newNode.getName(), newNode); - break; + if (newChild && !this.nodeIdsMap.has(child?._gvid)) { + this.nodeIdsMap.set(child?._gvid, newChild); } - case GVTypes.PROJECTION: { - let name = ''; - let extra: { [key: string]: any } = {}; - let sender, senderPort, receiver, receiverPort; - item.attr_list.forEach((singleAttr: any) => { - if (singleAttr.id === 'label') { - name = singleAttr.eq; - return; - } - if (singleAttr.type === 'attr') { - extra[singleAttr?.id] = singleAttr?.eq; - } - }); - if (item.edge_list.length === 2) { - sender = item.edge_list[0].id; - senderPort = item.edge_list[0]['port']['id']; - receiver = item.edge_list[1].id; - receiverPort = item.edge_list[1]['port']['id']; - } - newNode = new ProjectionLink(name, sender, senderPort, receiver, receiverPort, false, extra); - modelMap['links'].set(newNode.getName(), newNode); - break; + }); + + // Now da we have all the mechanisms in the idsMap we continue with the compositions + childrenCompositions.forEach((child: any) => { + let newChild = undefined; + newChild = this.nestedComposition(child, newNode, this.modelMap); + newNode.addChild(newChild); + + if (newChild && !this.nodeIdsMap.has(child?._gvid)) { + this.nodeIdsMap.set(child?._gvid, newChild); } - default: - // TODO: enable this in the future - // throw new Error(`Casting error, "${item.type}" type not known.`); - console.log(`Casting error, "${item.type}" type not known.`); + }); + + item.edges.forEach((edge: any) => { + let tail = this.nodeIdsMap.get(edge.tail); + let head = this.nodeIdsMap.get(edge.head); + // TODO: adjust the cast method below with tail and head + let newChild = this.castEdge(edge, tail, head, newNode, this.modelMap); + if (newChild && !this.linkIdsMap.has(edge?._gvid)) { + this.linkIdsMap.set(edge?._gvid, newChild); + } + newNode.addChild(newChild); + }); + + this.pnlModel[PNLClasses.COMPOSITION].push(newNode); + return newNode; + } + + nestedComposition( + item: MechanismNode|CompositionNode|ProjectionLink|any, + parent: CompositionNode, + modelMap: { [key: string]: Map }) + : MechanismNode|CompositionNode|ProjectionLink { + let newNode = item; + let extra: { [key: string]: any } = {}; + let ports : any = []; + let boundingBox = { + llx: 0, + lly: 0, + urx: 0, + ury: 0, + }; + if (item?.bb) { + let _vertices = item.bb.split(','); + boundingBox.llx = _vertices[0]; + boundingBox.lly = _vertices[1]; + boundingBox.urx = _vertices[2]; + boundingBox.ury = _vertices[3]; } + newNode = new CompositionNode(item?.name, parent, '', false, ports, extra, undefined, boundingBox); + modelMap['nodes'].set(newNode.getName(), newNode); + + // Iterates nodes of the nested composition to fill the children map/array + item.nodes.forEach((id: any) => { + let child = this.nodeIdsMap.get(id); + child.setParent(newNode); + }); + + item.edges.forEach((id: any) => { + // TODO: we should change the paternity of the link but not really needed now. + }); + + this.pnlModel[PNLClasses.COMPOSITION].push(newNode); return newNode; } -} \ No newline at end of file + + castMechanism( + item: MechanismNode|CompositionNode|ProjectionLink|any, + parent: CompositionNode|undefined, + modelMap: { [key: string]: Map }) + : MechanismNode|CompositionNode|ProjectionLink { + let newNode = item; + let ports: { [key: string]: any } = this.parseNodePorts(item?.name, PNLClasses.MECHANISM); + let extra: { [key: string]: any } = {}; + let coordinates = item.pos.split(','); + newNode = new MechanismNode( + item?.name, + parent, + '', + false, + ports, + extra, + coordinates[0], + coordinates[1], + ); + modelMap['nodes'].set(newNode.getName(), newNode); + this.pnlModel[PNLClasses.MECHANISM].push(newNode); + return newNode; + } + + castEdge( + item: MechanismNode|CompositionNode|ProjectionLink|any, + sender: MechanismNode|CompositionNode, + receiver: MechanismNode|CompositionNode, + parent: CompositionNode|undefined, + modelMap: { [key: string]: Map }) + : MechanismNode|CompositionNode|ProjectionLink { + let newNode = item; + let name = ''; + let extra: { [key: string]: any } = {}; + let senderPortName, receiverPortName; + // senderPortName = this.getPortName(item.tailport); + // receiverPortName = this.getPortName(item.headport); + senderPortName = item.tailport; + receiverPortName = item.headport; + newNode = new ProjectionLink( + name, + sender?.getName(), + senderPortName, + receiver.getName(), + receiverPortName, + false, + extra + ); + modelMap['links'].set(newNode.getName(), newNode); + this.pnlModel[PNLClasses.PROJECTION].push(newNode); + return newNode; + } + + getPortName(portString: string): string { + const [portType, ...portName] = portString.split('-'); + return portName.join('-'); + } +} diff --git a/src/model/links/ProjectionLink.ts b/src/model/links/ProjectionLink.ts index 8330f718..75c517a4 100644 --- a/src/model/links/ProjectionLink.ts +++ b/src/model/links/ProjectionLink.ts @@ -11,7 +11,7 @@ export default class ProjectionLink implements IMetaLinkConverter { receiverPort: string; extra: Object; isExpanded: Boolean; - innerClass: String; + innerClass: string; constructor(name: string, sender: string, senderPort: string, receiver: string, receiverPort: string, isExpanded?: Boolean, extra?: Object) { this.name = name; @@ -78,7 +78,7 @@ export default class ProjectionLink implements IMetaLinkConverter { ); } - getType(): String { + getType(): string { return this.innerClass; } -} \ No newline at end of file +} diff --git a/src/model/nodes/composition/CompositionNode.ts b/src/model/nodes/composition/CompositionNode.ts index 94bd3123..20574da6 100644 --- a/src/model/nodes/composition/CompositionNode.ts +++ b/src/model/nodes/composition/CompositionNode.ts @@ -6,60 +6,70 @@ import { MetaNode, MetaPort, Position, PortTypes } from '@metacell/meta-diagram' export default class CompositionNode extends MechanismNode { children: {[key: string]: any}; - childrenMap: Map; - innerClass: String; - parent: MechanismNode|CompositionNode|undefined; + childrenMap: Map; + innerClass: string; + boundingBox: {[key: string]: Number}|undefined; constructor( name: string, - parent: MechanismNode|CompositionNode|undefined, + parent: CompositionNode|undefined, icon?: string, isExpaded?: boolean, ports?: { [key: string]: Array }, extra?: Object, - children?: {[key: string]: any}) + children?: {[key: string]: any}, + boundingBox?: {[key: string]: Number}|undefined) { super(name, parent, icon, isExpaded, ports, extra); this.childrenMap = new Map(); this.children = children !== undefined ? children : { - 'mechanisms': [], - 'projections': [], - 'compositions': [], + [PNLClasses.MECHANISM]: [], + [PNLClasses.PROJECTION]: [], + [PNLClasses.COMPOSITION]: [], }; this.innerClass = PNLClasses.COMPOSITION; + this.boundingBox = boundingBox; } - addChild(child: any) { - if (child?.id === undefined) { - throw new TypeError('Each child should have a unique id string.'); + addChild(child: MechanismNode|CompositionNode|ProjectionLink) { + if (!this.childrenMap.has(child.getName())) { + this.childrenMap.set(child.getName(), child); } + this.children[child.getType()].push(child); + } - if (this.childrenMap.has(child.id)) { - return; + removeChild(child: MechanismNode|CompositionNode|ProjectionLink) { + if (this.childrenMap.has(child.getName())) { + this.childrenMap.delete(child.getName()); + } + switch (child.getType()) { + case PNLClasses.MECHANISM: { + this.children[PNLClasses.MECHANISM] = this.children[PNLClasses.MECHANISM].filter( (item: MechanismNode) => { + return item.getName() !== child.getName() + }) + break; + } + case PNLClasses.COMPOSITION: { + this.children[PNLClasses.COMPOSITION] = this.children[PNLClasses.COMPOSITION].filter( (item: MechanismNode) => { + return item.getName() !== child.getName() + }) + break; + } + case PNLClasses.PROJECTION: { + this.children[PNLClasses.PROJECTION] = this.children[PNLClasses.PROJECTION].filter( (item: MechanismNode) => { + return item.getName() !== child.getName() + }) + break; + } } - - // const castChild = ModelInterpreter.castObject(child, this.parent); - // this.childrenMap.set(child.id, castChild); - - // switch(castChild.getType()) { - // case PNLClasses.COMPOSITION: - // this.children[PNLClasses.COMPOSITION].push(castChild); - // break; - // case PNLClasses.MECHANISM: - // this.children[PNLClasses.MECHANISM].push(castChild); - // break; - // case PNLClasses.PROJECTION: - // this.children[PNLClasses.PROJECTION].push(castChild); - // break; - // } } getChildren() : {[key: string]: any} { return this.children; } - getType(): String { + getType(): string { return this.innerClass; } @@ -87,4 +97,4 @@ export default class CompositionNode extends MechanismNode { ) ); } -} \ No newline at end of file +} diff --git a/src/model/nodes/mechanism/MechanismNode.ts b/src/model/nodes/mechanism/MechanismNode.ts index f786e6f7..45f29db5 100644 --- a/src/model/nodes/mechanism/MechanismNode.ts +++ b/src/model/nodes/mechanism/MechanismNode.ts @@ -9,16 +9,20 @@ export default class MechanismNode implements IMetaDiagramConverter { isExpanded: Boolean; ports: { [key: string]: Array }; extra: Object; - innerClass: String; - parent: MechanismNode|CompositionNode|undefined; + innerClass: string; + parent: CompositionNode|undefined; + xPosition: number; + yPosition: number; constructor( name: string, - parent: MechanismNode|CompositionNode|undefined, + parent: CompositionNode|undefined, icon?: string, isExpaded?: boolean, ports?: { [key: string]: Array }, - extra?: Object) + extra?: Object, + xPosition?: number, + yPosition?: number) { this.name = name; this.icon = icon !== undefined ? icon : ""; @@ -27,6 +31,8 @@ export default class MechanismNode implements IMetaDiagramConverter { this.isExpanded = isExpaded !== undefined ? isExpaded : false; this.innerClass = PNLClasses.MECHANISM; this.parent = parent; + this.xPosition = xPosition || Math.random() * 900; + this.yPosition = yPosition || Math.random() * 900; } getName() : string { @@ -62,10 +68,19 @@ export default class MechanismNode implements IMetaDiagramConverter { return this.ports; } + setParent(newParent : CompositionNode) { + if (this.parent) { + this.parent.removeChild(this); + } + this.parent = newParent; + this.parent.addChild(this); + } + + getParent() : MechanismNode|CompositionNode|undefined { + return this.parent; + } + getMetaNode() : MetaNode { - // TODO: get position from the graphviz data - let x = 200 + Math.random() * 600; - let y = 200 + Math.random() * 600; let parent = this.parent ? this.parent.getMetaNode() : undefined; let ports: Array = [] // TODO: the MetaPort has the enum prefix cause the projections are created with that prefix @@ -73,11 +88,14 @@ export default class MechanismNode implements IMetaDiagramConverter { this.ports[PortTypes.INPUT_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.INPUT_PORT + '-' + port, PortTypes.INPUT_PORT + '-' + port, PortTypes.INPUT_PORT, new Position(0, 0), new Map()))); this.ports[PortTypes.OUTPUT_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.OUTPUT_PORT + '-' + port, PortTypes.OUTPUT_PORT + '-' + port, PortTypes.OUTPUT_PORT, new Position(0, 0), new Map()))); this.ports[PortTypes.PARAMETER_PORT].forEach((port: any) => ports.push(new MetaPort(PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT + '-' + port, PortTypes.PARAMETER_PORT, new Position(0, 0), new Map()))); + // this.ports[PortTypes.INPUT_PORT].forEach((port: any) => ports.push(new MetaPort(port, port, PortTypes.INPUT_PORT, new Position(0, 0), new Map()))); + // this.ports[PortTypes.OUTPUT_PORT].forEach((port: any) => ports.push(new MetaPort(port, port, PortTypes.OUTPUT_PORT, new Position(0, 0), new Map()))); + // this.ports[PortTypes.PARAMETER_PORT].forEach((port: any) => ports.push(new MetaPort(port, port, PortTypes.PARAMETER_PORT, new Position(0, 0), new Map()))); return new MetaNode( this.name, this.name, PNLClasses.MECHANISM, - new Position(x, y), + new Position(this.xPosition, this.yPosition), 'node-gray', parent, ports, @@ -92,7 +110,7 @@ export default class MechanismNode implements IMetaDiagramConverter { ); } - getType() : String { + getType() : string { return this.innerClass; } -} \ No newline at end of file +} diff --git a/src/resources/model.js b/src/resources/model.js index e506dbb3..51243f1a 100644 --- a/src/resources/model.js +++ b/src/resources/model.js @@ -1,27 +1,10 @@ +const modelJson = require('./model.json'); +const singleNodes = require('./single_nodes.json'); const { PNLClasses } = require("../constants"); -const composition = `digraph "Composition-0" { ` + -` graph [label="Composition-0" overlap=False rankdir=BT] ` + -` node [color=black fontname=arial fontsize=12 penwidth=1 shape=record]` + -` edge [fontname=arial fontsize=10]` + -` input [label=<
OutputPort-0
OutputPorts
Mechanism:
input
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=green penwidth=3 rank=source shape=plaintext]` + -` mid [label=<
OutputPort-0
OutputPorts
Mechanism:
mid
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=black penwidth=1 rank=same shape=plaintext]` + -` input:"OutputPort-OutputPort-0" -> mid:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]` + -` mid:"OutputPort-OutputPort-0" -> output:"InputPort-InputPort-0" [label="" arrowhead=normal color=black penwidth=1]` + -` output [label=<
OutputPort-0
OutputPorts
Mechanism:
output
ParameterPorts
intercept
slope
InputPorts
InputPort-0
> color=red penwidth=3 rank=max shape=plaintext]` + -`}`; - -// TODO: keep in mind that this below has been generated by _show_structure has suggested, but it required -// being incapsulated into the digraph in order to be consumed by the library we are using. -// Also in the interpreter we are purging the artificial graph and the first node for this same reason -// what done manually here will have to be implemented backend wise if there are free mechanisms outside composition. -const singleNode = `digraph "single_node" { graph` + -` single_node [label=<
OutputPort-0
=[0.]
single_node
=[[0.]]
intercept
=[0.]
slope
=[2.]
InputPort-0
=[0.]
>]` + -`}`; - const model = { - [PNLClasses.COMPOSITION]: [composition], - [PNLClasses.MECHANISM]: [singleNode] + [PNLClasses.COMPOSITION]: [modelJson], + [PNLClasses.MECHANISM]: singleNodes.objects } module.exports = { diff --git a/src/resources/model.json b/src/resources/model.json new file mode 100644 index 00000000..0a214842 --- /dev/null +++ b/src/resources/model.json @@ -0,0 +1,2212 @@ +{ + "name": "Composition-0", + "directed": true, + "strict": false, + "_draw_": [ + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#ffffff" + }, + { + "op": "P", + "points": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 619.0 + ], + [ + 266.0, + 619.0 + ], + [ + 266.0, + 0.0 + ] + ] + } + ], + "_ldraw_": [ + { + "op": "F", + "size": 14.0, + "face": "Times-Roman" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 133.0, + 7.8 + ], + "align": "c", + "width": 82.0, + "text": "Composition-0" + } + ], + "bb": "0,0,266,619", + "label": "Composition-0", + "lheight": "0.21", + "lp": "133,11.5", + "lwidth": "1.14", + "overlap": "False", + "rankdir": "BT", + "xdotversion": "1.7", + "_subgraph_cnt": 0, + "objects": [ + { + "_gvid": 0, + "name": "input", + "_ldraw_": [ + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fffff0" + }, + { + "op": "P", + "points": [ + [ + 8.0, + 27.0 + ], + [ + 8.0, + 195.0 + ], + [ + 258.0, + 195.0 + ], + [ + 258.0, + 27.0 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 14.0, + 141.0 + ], + [ + 14.0, + 189.0 + ], + [ + 252.0, + 189.0 + ], + [ + 252.0, + 141.0 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 18.0, + 164.0 + ], + [ + 18.0, + 185.0 + ], + [ + 248.0, + 185.0 + ], + [ + 248.0, + 164.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 19.0, + 165.0 + ], + [ + 19.0, + 184.0 + ], + [ + 247.0, + 184.0 + ], + [ + 247.0, + 165.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 96.0, + 172.4 + ], + "align": "l", + "width": 74.0, + "text": "OutputPort-0" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 98.0, + 149.4 + ], + "align": "l", + "width": 70.0, + "text": "OutputPorts" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 14.0, + 116.4 + ], + "align": "l", + "width": 66.0, + "text": "Mechanism" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 80.0, + 116.4 + ], + "align": "l", + "width": 4.0, + "text": ":" + }, + { + "op": "F", + "size": 16.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 29.0, + 101.2 + ], + "align": "l", + "width": 40.0, + "text": "input" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 89.0, + 86.0 + ], + [ + 89.0, + 136.0 + ], + [ + 252.0, + 136.0 + ], + [ + 252.0, + 86.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 93.0, + 108.9 + ], + "align": "l", + "width": 90.0, + "text": "ParameterPorts" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 189.0, + 90.0 + ], + [ + 189.0, + 132.0 + ], + [ + 248.0, + 132.0 + ], + [ + 248.0, + 90.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 190.0, + 112.0 + ], + [ + 190.0, + 131.0 + ], + [ + 247.0, + 131.0 + ], + [ + 247.0, + 112.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 193.0, + 119.4 + ], + "align": "l", + "width": 51.0, + "text": "intercept" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 190.0, + 91.0 + ], + [ + 190.0, + 110.0 + ], + [ + 247.0, + 110.0 + ], + [ + 247.0, + 91.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 202.5, + 98.4 + ], + "align": "l", + "width": 32.0, + "text": "slope" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 14.0, + 33.0 + ], + [ + 14.0, + 81.0 + ], + [ + 252.0, + 81.0 + ], + [ + 252.0, + 33.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 102.5, + 68.4 + ], + "align": "l", + "width": 61.0, + "text": "InputPorts" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 18.0, + 37.0 + ], + [ + 18.0, + 58.0 + ], + [ + 248.0, + 58.0 + ], + [ + 248.0, + 37.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 19.0, + 38.0 + ], + [ + 19.0, + 57.0 + ], + [ + 247.0, + 57.0 + ], + [ + 247.0, + 38.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 101.0, + 45.4 + ], + "align": "l", + "width": 64.0, + "text": "InputPort-0" + }, + { + "op": "S", + "style": "setlinewidth(3)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#00ff00" + }, + { + "op": "p", + "points": [ + [ + 9.5, + 28.5 + ], + [ + 9.5, + 193.5 + ], + [ + 256.5, + 193.5 + ], + [ + 256.5, + 28.5 + ] + ] + } + ], + "color": "green", + "fontname": "arial", + "fontsize": "12", + "height": "2.4444", + "label": "
OutputPort-0
OutputPorts
Mechanism:
input
ParameterPorts
intercept
slope
InputPorts
InputPort-0
", + "penwidth": "3", + "pos": "133,111", + "rank": "source", + "shape": "plaintext", + "width": "3.6944" + }, + { + "_gvid": 1, + "name": "mid", + "_ldraw_": [ + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fffff0" + }, + { + "op": "P", + "points": [ + [ + 10.0, + 239.0 + ], + [ + 10.0, + 403.0 + ], + [ + 256.0, + 403.0 + ], + [ + 256.0, + 239.0 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 14.0, + 351.0 + ], + [ + 14.0, + 399.0 + ], + [ + 252.0, + 399.0 + ], + [ + 252.0, + 351.0 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 18.0, + 374.0 + ], + [ + 18.0, + 395.0 + ], + [ + 248.0, + 395.0 + ], + [ + 248.0, + 374.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 19.0, + 375.0 + ], + [ + 19.0, + 394.0 + ], + [ + 247.0, + 394.0 + ], + [ + 247.0, + 375.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 96.0, + 382.4 + ], + "align": "l", + "width": 74.0, + "text": "OutputPort-0" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 98.0, + 359.4 + ], + "align": "l", + "width": 70.0, + "text": "OutputPorts" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 14.0, + 326.4 + ], + "align": "l", + "width": 66.0, + "text": "Mechanism" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 80.0, + 326.4 + ], + "align": "l", + "width": 4.0, + "text": ":" + }, + { + "op": "F", + "size": 16.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 34.5, + 311.2 + ], + "align": "l", + "width": 29.0, + "text": "mid" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 89.0, + 296.0 + ], + [ + 89.0, + 346.0 + ], + [ + 252.0, + 346.0 + ], + [ + 252.0, + 296.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 93.0, + 318.9 + ], + "align": "l", + "width": 90.0, + "text": "ParameterPorts" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 189.0, + 300.0 + ], + [ + 189.0, + 342.0 + ], + [ + 248.0, + 342.0 + ], + [ + 248.0, + 300.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 190.0, + 322.0 + ], + [ + 190.0, + 341.0 + ], + [ + 247.0, + 341.0 + ], + [ + 247.0, + 322.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 193.0, + 329.4 + ], + "align": "l", + "width": 51.0, + "text": "intercept" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 190.0, + 301.0 + ], + [ + 190.0, + 320.0 + ], + [ + 247.0, + 320.0 + ], + [ + 247.0, + 301.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 202.5, + 308.4 + ], + "align": "l", + "width": 32.0, + "text": "slope" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 14.0, + 243.0 + ], + [ + 14.0, + 291.0 + ], + [ + 252.0, + 291.0 + ], + [ + 252.0, + 243.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 102.5, + 278.4 + ], + "align": "l", + "width": 61.0, + "text": "InputPorts" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 18.0, + 247.0 + ], + [ + 18.0, + 268.0 + ], + [ + 248.0, + 268.0 + ], + [ + 248.0, + 247.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 19.0, + 248.0 + ], + [ + 19.0, + 267.0 + ], + [ + 247.0, + 267.0 + ], + [ + 247.0, + 248.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 101.0, + 255.4 + ], + "align": "l", + "width": 64.0, + "text": "InputPort-0" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "p", + "points": [ + [ + 10.0, + 239.0 + ], + [ + 10.0, + 403.0 + ], + [ + 256.0, + 403.0 + ], + [ + 256.0, + 239.0 + ] + ] + } + ], + "color": "black", + "fontname": "arial", + "fontsize": "12", + "height": "2.3889", + "label": "
OutputPort-0
OutputPorts
Mechanism:
mid
ParameterPorts
intercept
slope
InputPorts
InputPort-0
", + "penwidth": "1", + "pos": "133,321", + "rank": "same", + "shape": "plaintext", + "width": "3.6389" + }, + { + "_gvid": 2, + "name": "output", + "_ldraw_": [ + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fffff0" + }, + { + "op": "P", + "points": [ + [ + 8.0, + 447.0 + ], + [ + 8.0, + 615.0 + ], + [ + 258.0, + 615.0 + ], + [ + 258.0, + 447.0 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 14.0, + 561.0 + ], + [ + 14.0, + 609.0 + ], + [ + 252.0, + 609.0 + ], + [ + 252.0, + 561.0 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 18.0, + 584.0 + ], + [ + 18.0, + 605.0 + ], + [ + 248.0, + 605.0 + ], + [ + 248.0, + 584.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 19.0, + 585.0 + ], + [ + 19.0, + 604.0 + ], + [ + 247.0, + 604.0 + ], + [ + 247.0, + 585.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 96.0, + 592.4 + ], + "align": "l", + "width": 74.0, + "text": "OutputPort-0" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 98.0, + 569.4 + ], + "align": "l", + "width": 70.0, + "text": "OutputPorts" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 14.0, + 536.4 + ], + "align": "l", + "width": 66.0, + "text": "Mechanism" + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 80.0, + 536.4 + ], + "align": "l", + "width": 4.0, + "text": ":" + }, + { + "op": "F", + "size": 16.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 24.0, + 521.2 + ], + "align": "l", + "width": 50.0, + "text": "output" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 89.0, + 506.0 + ], + [ + 89.0, + 556.0 + ], + [ + 252.0, + 556.0 + ], + [ + 252.0, + 506.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 93.0, + 528.9 + ], + "align": "l", + "width": 90.0, + "text": "ParameterPorts" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 189.0, + 510.0 + ], + [ + 189.0, + 552.0 + ], + [ + 248.0, + 552.0 + ], + [ + 248.0, + 510.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 190.0, + 532.0 + ], + [ + 190.0, + 551.0 + ], + [ + 247.0, + 551.0 + ], + [ + 247.0, + 532.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 193.0, + 539.4 + ], + "align": "l", + "width": 51.0, + "text": "intercept" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 190.0, + 511.0 + ], + [ + 190.0, + 530.0 + ], + [ + 247.0, + 530.0 + ], + [ + 247.0, + 511.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 202.5, + 518.4 + ], + "align": "l", + "width": 32.0, + "text": "slope" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 14.0, + 453.0 + ], + [ + 14.0, + 501.0 + ], + [ + 252.0, + 501.0 + ], + [ + 252.0, + 453.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 3 + }, + { + "op": "T", + "pt": [ + 102.5, + 488.4 + ], + "align": "l", + "width": 61.0, + "text": "InputPorts" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 18.0, + 457.0 + ], + [ + 18.0, + 478.0 + ], + [ + 248.0, + 478.0 + ], + [ + 248.0, + 457.0 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 19.0, + 458.0 + ], + [ + 19.0, + 477.0 + ], + [ + 247.0, + 477.0 + ], + [ + 247.0, + 458.0 + ] + ] + }, + { + "op": "F", + "size": 12.0, + "face": "arial" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 101.0, + 465.4 + ], + "align": "l", + "width": 64.0, + "text": "InputPort-0" + }, + { + "op": "S", + "style": "setlinewidth(3)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#ff0000" + }, + { + "op": "p", + "points": [ + [ + 9.5, + 448.5 + ], + [ + 9.5, + 613.5 + ], + [ + 256.5, + 613.5 + ], + [ + 256.5, + 448.5 + ] + ] + } + ], + "color": "red", + "fontname": "arial", + "fontsize": "12", + "height": "2.4444", + "label": "
OutputPort-0
OutputPorts
Mechanism:
output
ParameterPorts
intercept
slope
InputPorts
InputPort-0
", + "penwidth": "3", + "pos": "133,531", + "rank": "max", + "shape": "plaintext", + "width": "3.6944" + } + ], + "edges": [ + { + "_gvid": 0, + "tail": 0, + "head": 1, + "_draw_": [ + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "b", + "points": [ + [ + 133.0, + 186.0 + ], + [ + 133.0, + 208.92 + ], + [ + 133.0, + 217.06 + ], + [ + 133.0, + 235.83 + ] + ] + } + ], + "_hdraw_": [ + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "C", + "grad": "none", + "color": "#000000" + }, + { + "op": "P", + "points": [ + [ + 129.5, + 236.0 + ], + [ + 133.0, + 246.0 + ], + [ + 136.5, + 236.0 + ] + ] + } + ], + "arrowhead": "normal", + "color": "black", + "fontname": "arial", + "fontsize": "10", + "headport": "InputPort-InputPort-0", + "label": "", + "penwidth": "1", + "pos": "e,133,246 133,186 133,208.92 133,217.06 133,235.83", + "tailport": "OutputPort-OutputPort-0" + }, + { + "_gvid": 1, + "tail": 1, + "head": 2, + "_draw_": [ + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "b", + "points": [ + [ + 133.0, + 396.0 + ], + [ + 133.0, + 418.92 + ], + [ + 133.0, + 427.06 + ], + [ + 133.0, + 445.83 + ] + ] + } + ], + "_hdraw_": [ + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "C", + "grad": "none", + "color": "#000000" + }, + { + "op": "P", + "points": [ + [ + 129.5, + 446.0 + ], + [ + 133.0, + 456.0 + ], + [ + 136.5, + 446.0 + ] + ] + } + ], + "arrowhead": "normal", + "color": "black", + "fontname": "arial", + "fontsize": "10", + "headport": "InputPort-InputPort-0", + "label": "", + "penwidth": "1", + "pos": "e,133,456 133,396 133,418.92 133,427.06 133,445.83", + "tailport": "OutputPort-OutputPort-0" + } + ] +} \ No newline at end of file diff --git a/src/resources/single_nodes.json b/src/resources/single_nodes.json new file mode 100644 index 00000000..cc54c58b --- /dev/null +++ b/src/resources/single_nodes.json @@ -0,0 +1,592 @@ +{ + "name": "single_nodes", + "directed": true, + "strict": false, + "_draw_": [ + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#ffffff" + }, + { + "op": "P", + "points": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 200.82 + ], + [ + 251.73, + 200.82 + ], + [ + 251.73, + 0.0 + ] + ] + } + ], + "bb": "0,0,251.73,200.82", + "xdotversion": "1.7", + "_subgraph_cnt": 0, + "objects": [ + { + "_gvid": 0, + "name": "single_node", + "_draw_": [ + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "e", + "rect": [ + 125.87, + 100.41, + 125.73, + 100.32 + ] + } + ], + "_ldraw_": [ + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fffff0" + }, + { + "op": "P", + "points": [ + [ + 44.87, + 33.41 + ], + [ + 44.87, + 167.41 + ], + [ + 206.87, + 167.41 + ], + [ + 206.87, + 33.41 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 48.87, + 132.41 + ], + [ + 48.87, + 163.41 + ], + [ + 202.87, + 163.41 + ], + [ + 202.87, + 132.41 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 52.87, + 136.41 + ], + [ + 52.87, + 159.41 + ], + [ + 198.87, + 159.41 + ], + [ + 198.87, + 136.41 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 53.87, + 137.41 + ], + [ + 53.87, + 158.41 + ], + [ + 197.87, + 158.41 + ], + [ + 197.87, + 137.41 + ] + ] + }, + { + "op": "F", + "size": 14.0, + "face": "Times-Roman" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "t", + "fontchar": 1 + }, + { + "op": "T", + "pt": [ + 85.87, + 145.21 + ], + "align": "l", + "width": 80.0, + "text": "OutputPort-0" + }, + { + "op": "F", + "size": 16.0, + "face": "Times-Roman" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 48.87, + 97.61 + ], + "align": "l", + "width": 81.0, + "text": "single_node" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 134.87, + 73.41 + ], + [ + 134.87, + 127.41 + ], + [ + 202.87, + 127.41 + ], + [ + 202.87, + 73.41 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 138.87, + 77.41 + ], + [ + 138.87, + 123.41 + ], + [ + 198.87, + 123.41 + ], + [ + 198.87, + 77.41 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 139.87, + 101.41 + ], + [ + 139.87, + 122.41 + ], + [ + 197.87, + 122.41 + ], + [ + 197.87, + 101.41 + ] + ] + }, + { + "op": "F", + "size": 14.0, + "face": "Times-Roman" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 142.87, + 109.21 + ], + "align": "l", + "width": 52.0, + "text": "intercept" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 139.87, + 78.41 + ], + [ + 139.87, + 99.41 + ], + [ + 197.87, + 99.41 + ], + [ + 197.87, + 78.41 + ] + ] + }, + { + "op": "F", + "size": 14.0, + "face": "Times-Roman" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 153.87, + 86.21 + ], + "align": "l", + "width": 30.0, + "text": "slope" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#fafad0" + }, + { + "op": "P", + "points": [ + [ + 48.87, + 37.41 + ], + [ + 48.87, + 68.41 + ], + [ + 202.87, + 68.41 + ], + [ + 202.87, + 37.41 + ] + ] + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fffffe00" + }, + { + "op": "C", + "grad": "none", + "color": "#eee8aa" + }, + { + "op": "P", + "points": [ + [ + 52.87, + 41.41 + ], + [ + 52.87, + 64.41 + ], + [ + 198.87, + 64.41 + ], + [ + 198.87, + 41.41 + ] + ] + }, + { + "op": "S", + "style": "setlinewidth(2)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#fafad2" + }, + { + "op": "p", + "points": [ + [ + 53.87, + 42.41 + ], + [ + 53.87, + 63.41 + ], + [ + 197.87, + 63.41 + ], + [ + 197.87, + 42.41 + ] + ] + }, + { + "op": "F", + "size": 14.0, + "face": "Times-Roman" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "T", + "pt": [ + 90.87, + 50.21 + ], + "align": "l", + "width": 70.0, + "text": "InputPort-0" + }, + { + "op": "S", + "style": "setlinewidth(1)" + }, + { + "op": "S", + "style": "solid" + }, + { + "op": "c", + "grad": "none", + "color": "#000000" + }, + { + "op": "p", + "points": [ + [ + 44.87, + 33.41 + ], + [ + 44.87, + 167.41 + ], + [ + 206.87, + 167.41 + ], + [ + 206.87, + 33.41 + ] + ] + } + ], + "height": "2.7891", + "label": "
OutputPort-0
single_node
intercept
slope
InputPort-0
", + "pos": "125.87,100.41", + "width": "3.4963" + } + ] +} \ No newline at end of file diff --git a/src/services/queryService.ts b/src/services/queryService.ts index 25de92c5..873351ac 100644 --- a/src/services/queryService.ts +++ b/src/services/queryService.ts @@ -16,6 +16,8 @@ export default class QueryService { return '[(InputPort InputPort-0), (ParameterPort intercept), (ParameterPort slope), (OutputPort OutputPort-0)]' case 'mid': return '[(InputPort InputPort-0), (ParameterPort intercept), (ParameterPort slope), (OutputPort OutputPort-0)]' + case 'mid2': + return '[(InputPort InputPort-0), (ParameterPort intercept), (ParameterPort slope), (OutputPort OutputPort-0)]' case 'output': return '[(InputPort InputPort-0), (ParameterPort intercept), (ParameterPort slope), (OutputPort OutputPort-0)]' case 'single_node': @@ -32,4 +34,3 @@ export default class QueryService { } } -