From 92228d83b491db34078bfcbf601f13dd25aca60e Mon Sep 17 00:00:00 2001 From: privrja Date: Fri, 23 Apr 2021 08:50:56 +0200 Subject: [PATCH 1/6] Clear --- app.js | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index b233aaa3..fe598d2e 100644 --- a/app.js +++ b/app.js @@ -15,7 +15,7 @@ var canUseDOM = !!( * @typicalname SmilesDrawer */ var SmilesDrawer = { - Version: '2.1.4' + Version: '2.1.5' }; SmilesDrawer.Drawer = Drawer; diff --git a/package-lock.json b/package-lock.json index c1a3c319..c99c203b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "smiles-drawer", - "version": "2.1.4", + "version": "2.1.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 15e15dbc..3c42a9d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "smiles-drawer", - "version": "2.1.4", + "version": "2.1.5", "description": "A SMILES drawer and parser. Generate molecular structure depictions in pure JavaScript. With new feature to compute building blocks from sequence.", "main": "./app.js", "repository": "https://github.com/privrja/smilesDrawer.git", From 07e7bf9d6e6140a124c9169bc926afa43ff63920 Mon Sep 17 00:00:00 2001 From: privrja Date: Fri, 23 Apr 2021 08:51:14 +0200 Subject: [PATCH 2/6] Clear --- dist/smiles-drawer.js | 2 +- dist/smiles-drawer.min.js | 2 +- dist/smiles-drawer.min.js.map | 2 +- doc/ArrayHelper.html | 2 +- doc/ArrayHelper.js.html | 2 +- doc/Atom.html | 2 +- doc/Atom.js.html | 2 +- doc/CanvasWrapper.html | 2 +- doc/CanvasWrapper.js.html | 2 +- doc/DecayPoint.js.html | 2 +- doc/Drawer.html | 2 +- doc/Drawer.js.html | 2 +- doc/Edge.html | 2 +- doc/Edge.js.html | 2 +- doc/Graph.html | 2 +- doc/Graph.js.html | 2 +- doc/Line.html | 2 +- doc/Line.js.html | 2 +- doc/MathHelper.html | 2 +- doc/MathHelper.js.html | 2 +- doc/MutableBoolean.html | 2 +- doc/MutableBoolean.js.html | 2 +- doc/MutableCounter.html | 2 +- doc/MutableCounter.js.html | 2 +- doc/Ring.html | 2 +- doc/Ring.js.html | 2 +- doc/RingConnection.html | 2 +- doc/RingConnection.js.html | 2 +- doc/SSSR.html | 2 +- doc/SSSR.js.html | 2 +- doc/SvgDrawer.js.html | 2 +- doc/SvgWrapper.js.html | 2 +- doc/ThemeManager.js.html | 2 +- doc/UtilityFunctions.js.html | 2 +- doc/Vector2.html | 2 +- doc/Vector2.js.html | 2 +- doc/Vertex.html | 2 +- doc/Vertex.js.html | 2 +- doc/VertexState.js.html | 2 +- doc/global.html | 2 +- doc/index.html | 2 +- 41 files changed, 41 insertions(+), 41 deletions(-) diff --git a/dist/smiles-drawer.js b/dist/smiles-drawer.js index 24349cfc..ec07e9de 100644 --- a/dist/smiles-drawer.js +++ b/dist/smiles-drawer.js @@ -16,7 +16,7 @@ var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.do */ var SmilesDrawer = { - Version: '2.1.4' + Version: '2.1.5' }; SmilesDrawer.Drawer = Drawer; SmilesDrawer.Parser = Parser; diff --git a/dist/smiles-drawer.min.js b/dist/smiles-drawer.min.js index 3680530e..0f55596a 100644 --- a/dist/smiles-drawer.min.js +++ b/dist/smiles-drawer.min.js @@ -1,4 +1,4 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i{const context=canvas.getContext("2d");context.clearRect(0,0,canvas.width,canvas.height)})},SmilesDrawer.parse=function(smiles,successCallback,errorCallback){try{successCallback&&successCallback(Parser.parse(smiles))}catch(err){errorCallback&&errorCallback(err)}},canUseDOM&&(window.SmilesDrawer=SmilesDrawer),Array.prototype.fill||Object.defineProperty(Array.prototype,"fill",{value:function(value){if(null==this)throw new TypeError("this is null or not defined");for(var O=Object(this),len=O.length>>>0,start=arguments[1],relativeStart=start>>0,k=0>relativeStart?_Mathmax(len+relativeStart,0):_Mathmin(relativeStart,len),end=arguments[2],relativeEnd=void 0===end?len:end>>0,final=0>relativeEnd?_Mathmax(len+relativeEnd,0):_Mathmin(relativeEnd,len);kp.x&&(minX=p.x),minY>p.y&&(minY=p.y)}var padding=this.opts.padding;maxX+=padding,maxY+=padding,minX-=padding,minY-=padding,this.drawingWidth=maxX-minX,this.drawingHeight=maxY-minY;var scaleX=this.canvas.offsetWidth/this.drawingWidth,scaleY=this.canvas.offsetHeight/this.drawingHeight,scale=scaleXalpha&&(ctx.globalAlpha=alpha),ctx.strokeStyle=gradient,ctx.stroke(),ctx.restore()}drawWedge(line,width=1){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,shortLine=line.clone().shorten(5),l=shortLine.getLeftVector().clone(),r=shortLine.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone(),l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),start=l,end=r;isRightChiralCenter&&(start=r,end=l);let t=Vector2.add(start,Vector2.multiplyScalar(normals[0],this.halfBondThickness)),u=Vector2.add(end,Vector2.multiplyScalar(normals[0],1.5+this.halfBondThickness)),v=Vector2.add(end,Vector2.multiplyScalar(normals[1],1.5+this.halfBondThickness)),w=Vector2.add(start,Vector2.multiplyScalar(normals[1],this.halfBondThickness));ctx.beginPath(),ctx.moveTo(t.x,t.y),ctx.lineTo(u.x,u.y),ctx.lineTo(v.x,v.y),ctx.lineTo(w.x,w.y);let gradient=this.ctx.createRadialGradient(r.x,r.y,this.opts.bondLength,r.x,r.y,0);gradient.addColorStop(.4,this.themeManager.getColor(line.getLeftElement())||this.themeManager.getColor("C")),gradient.addColorStop(.6,this.themeManager.getColor(line.getRightElement())||this.themeManager.getColor("C")),ctx.fillStyle=gradient,ctx.fill(),ctx.restore()}drawDashedWedge(line){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),shortLine=line.clone(),start,end,sStart,sEnd;isRightChiralCenter?(start=r,end=l,shortLine.shortenRight(1),sStart=shortLine.getRightVector().clone(),sEnd=shortLine.getLeftVector().clone()):(start=l,end=r,shortLine.shortenLeft(1),sStart=shortLine.getLeftVector().clone(),sEnd=shortLine.getRightVector().clone()),sStart.x+=offsetX,sStart.y+=offsetY,sEnd.x+=offsetX,sEnd.y+=offsetY;let dir=Vector2.subtract(end,start).normalize();ctx.strokeStyle=this.themeManager.getColor("C"),ctx.lineCap="round",ctx.lineWidth=this.opts.bondThickness,ctx.beginPath();let length=line.getLength(),step=1.25/(length/(3*this.opts.bondThickness)),changed=!1;for(var t=0;1>t;t+=step){let to=Vector2.multiplyScalar(dir,t*length),startDash=Vector2.add(start,to),width=1.5*t,dashOffset=Vector2.multiplyScalar(normals[0],width);!changed&&.5this.opts.fontSizeLarge?dim.width:this.opts.fontSizeLarge;r/=1.5,ctx.globalCompositeOperation="destination-out",ctx.beginPath(),ctx.arc(x+offsetX,y+offsetY,r,0,MathHelper.twoPI,!0),ctx.closePath(),ctx.fill(),ctx.globalCompositeOperation="source-over";let cursorPos=-dim.width/2,cursorPosLeft=-dim.width/2;ctx.fillStyle=this.themeManager.getColor(elementName),ctx.fillText(elementName,x+offsetX+cursorPos,y+this.opts.halfFontSizeLarge+offsetY),cursorPos+=dim.width,charge&&(ctx.font=this.fontSmall,ctx.fillText(chargeText,x+offsetX+cursorPos,y-this.opts.fifthFontSizeSmall+offsetY),cursorPos+=chargeWidth),0maxDist&&(maxDist=dist,a=i,b=j)}let angle=-Vector2.subtract(this.graph.vertices[a].position,this.graph.vertices[b].position).angle();if(!isNaN(angle)){let remainder=angle%.523599;.2617995>remainder?angle-=remainder:angle+=.523599-remainder;for(let i=0;i{if(counts.has(e)){let count=counts.get(e);molecularFormula+=e+(1vertexA.value.getRingbondCount()||1>vertexB.value.getRingbondCount())return null;for(var i=0;isubTreeDepthB&&(a=edge.sourceId,b=edge.targetId);let subTreeOverlap=this.getSubtreeOverlapScore(b,a,overlapScore.vertexScores);if(subTreeOverlap.value>this.opts.overlapSensitivity){let vertexA=this.graph.vertices[a],vertexB=this.graph.vertices[b],neighboursB=vertexB.getNeighbours(a);if(1===neighboursB.length){let neighbour=this.graph.vertices[neighboursB[0]],angle=neighbour.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbour.id,vertexB.id,angle,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?this.rotateSubtree(neighbour.id,vertexB.id,-angle,vertexB.position):this.totalOverlapScore=newTotalOverlapScore}else if(2===neighboursB.length){if(0!==vertexB.value.rings.length&&0!==vertexA.value.rings.length)continue;let neighbourA=this.graph.vertices[neighboursB[0]],neighbourB=this.graph.vertices[neighboursB[1]];if(1===neighbourA.value.rings.length&&1===neighbourB.value.rings.length){if(neighbourA.value.rings[0]!==neighbourB.value.rings[0])continue;}else if(0!==neighbourA.value.rings.length||0!==neighbourB.value.rings.length)continue;else{let angleA=neighbourA.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120)),angleB=neighbourB.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbourA.id,vertexB.id,angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,angleB,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?(this.rotateSubtree(neighbourA.id,vertexB.id,-angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,-angleB,vertexB.position)):this.totalOverlapScore=newTotalOverlapScore}}overlapScore=this.getOverlapScore()}}}this.resolveSecondaryOverlaps(overlapScore.scores),this.opts.isomeric&&this.annotateStereochemistry(),this.opts.compactDrawing&&"default"===this.opts.atomVisualization&&this.initPseudoElements(),this.rotateDrawing()}initRings(){let openBonds=new Map;for(let i=this.graph.vertices.length-1,vertex;0<=i;i--)if(vertex=this.graph.vertices[i],0!==vertex.value.ringbonds.length)for(let j=0;jneighbour.value.rings.length&&!neighbour.value.bridgedRing||neighbour.value.bridgedRing&&2>neighbour.value.originalRings.length)&&(vertex.value.isDrawn=!1)}}getBridgedRingRings(ringId){let involvedRings=[],that=this,recurse=function(r){let ring=that.getRing(r);involvedRings.push(r);for(let i=0,n;imaxSize&&(maxSize=size,largestCommonRing=ring)}return largestCommonRing}getVerticesAt(position,radius,excludeVertexId){let locals=[];for(let i=0,vertex;ii;){let a=this.graph.vertices[i],b=this.graph.vertices[j];if(!a.value.isDrawn||!b.value.isDrawn)continue;let dist=Vector2.subtract(a.position,b.position).lengthSq();if(disttotalSideCount[1]?0:1,sideCount:sideCount,position:sideCount[0]>sideCount[1]?0:1,anCount:anCount,bnCount:bnCount}}setRingCenter(ring){let ringSize=ring.getSize(),total=new Vector2(0,0);for(let i=0;is.sideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.sideCount[0]s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.totalSideCount[0]<=s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}}else if("#"===edge.bondType){normals[0].multiplyScalar(that.opts.bondSpacing/1.5),normals[1].multiplyScalar(that.opts.bondSpacing/1.5);let lineA=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)),lineB=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));this.canvasWrapper.drawLine(lineA),this.canvasWrapper.drawLine(lineB),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if("."===edge.bondType);else{let isChiralCenterA=vertexA.value.isStereoCenter,isChiralCenterB=vertexB.value.isStereoCenter;"up"===edge.wedge?this.canvasWrapper.drawWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):"down"===edge.wedge?this.canvasWrapper.drawDashedWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay)))}if(debug){let midpoint=Vector2.midpoint(a,b);this.canvasWrapper.drawDebugText(midpoint.x,midpoint.y,"e: "+edgeId)}}drawVertices(debug){for(let i=0;i_Mathabs(_MathPI-angle)&&this.canvasWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);this.canvasWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else;}if(this.opts.debug)for(let i=0,center;iring.rings.length)&&(vertex.angle=a,vertex.positioned=!0)},startVertexId,previousVertex?previousVertex.id:null);ring.positioned=!0,ring.center=center;for(let i=0,neighbour;iVector2.subtract(center,normals[0]).lengthSq()&&(nextCenter=normals[1]);let posA=Vector2.subtract(vertexA.position,nextCenter),posB=Vector2.subtract(vertexB.position,nextCenter);-1===posA.clockwise(posB)?!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexA,vertexB):!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexB,vertexA)}else if(1===vertices.length){ring.isSpiro=!0,neighbour.isSpiro=!0;let vertexA=this.graph.vertices[vertices[0]],nextCenter=Vector2.subtract(center,vertexA.position);nextCenter.invert(),nextCenter.normalize();let r=MathHelper.polyCircumradius(this.opts.bondLength,neighbour.getSize());nextCenter.multiplyScalar(r),nextCenter.add(vertexA.position),neighbour.positioned||this.createRing(neighbour,nextCenter,vertexA)}}for(let i=0;ithat.opts.overlapSensitivity&&(score+=s,count++);let position=that.graph.vertices[vertex.id].position.clone();position.multiplyScalar(s),center.add(position)}}),center.divide(score),{value:score/count,center:center}}getCurrentCenterOfMass(){let total=new Vector2(0,0),count=0;for(let i=0,vertex;itotal&&(this.rotateSubtree(a.id,overlap.common.id,2*angle,overlap.common.position),this.rotateSubtree(b.id,overlap.common.id,-2*angle,overlap.common.position))}else 1!==overlap.vertices.length||2!==overlap.rings.length}resolveSecondaryOverlaps(scores){for(let i=0;ithis.opts.overlapSensitivity){let vertex=this.graph.vertices[scores[i].id];if(vertex.isTerminal()){let closest=this.getClosestVertex(vertex);if(closest){let closestPosition=null;closestPosition=closest.isTerminal()?0===closest.id?this.graph.vertices[1].position:closest.previousPosition:0===closest.id?this.graph.vertices[1].position:closest.position;let vertexPreviousPosition=0===vertex.id?this.graph.vertices[1].position:vertex.previousPosition;vertex.position.rotateAwayFrom(closestPosition,vertexPreviousPosition,MathHelper.toRad(20))}}}}getLastVertexWithAngle(vertexId){let angle=0,vertex=null;for(;!angle&&vertexId;)vertex=this.graph.vertices[vertexId],angle=vertex.angle,vertexId=vertex.parentVertexId;return vertex}createNextBond(vertex,previousVertex=null,angle=0,originShortest=!1,skipPositioning=!1){if(vertex.positioned&&!skipPositioning)return;let doubleBondConfigSet=!1;if(previousVertex){let edge=this.graph.getEdge(vertex.id,previousVertex.id);("/"===edge.bondType||"\\"===edge.bondType)&&1==++this.doubleBondConfigCount%2&&null===this.doubleBondConfig&&(this.doubleBondConfig=edge.bondType,doubleBondConfigSet=!0,null===previousVertex.parentVertexId&&vertex.value.branchBond&&("/"===this.doubleBondConfig?this.doubleBondConfig="\\":"\\"===this.doubleBondConfig&&(this.doubleBondConfig="/")))}if(!skipPositioning)if(!previousVertex){let dummy=new Vector2(this.opts.bondLength,0);dummy.rotate(MathHelper.toRad(-60)),vertex.previousPosition=dummy,vertex.setPosition(this.opts.bondLength,0),vertex.angle=MathHelper.toRad(-60),null===vertex.value.bridgedRing&&(vertex.positioned=!0)}else if(0a?_Mathmax2(-1.0472,a):1.0472;else if(!a){let v=this.getLastVertexWithAngle(vertex.id);a=v.angle,a||(a=1.0472)}if(previousVertex&&!doubleBondConfigSet){let bondType=this.graph.getEdge(vertex.id,nextVertex.id).bondType;"/"===bondType?("/"===this.doubleBondConfig||"\\"===this.doubleBondConfig&&(a=-a),this.doubleBondConfig=null):"\\"===bondType&&("/"===this.doubleBondConfig?a=-a:"\\"===this.doubleBondConfig,this.doubleBondConfig=null)}nextVertex.angle=originShortest?a:-a,this.createNextBond(nextVertex,vertex,previousAngle+nextVertex.angle)}}else if(2===neighbours.length){let a=vertex.angle;a||(a=1.0472);let subTreeDepthA=this.graph.getTreeDepth(neighbours[0],vertex.id),subTreeDepthB=this.graph.getTreeDepth(neighbours[1],vertex.id),l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]];l.value.subtreeDepth=subTreeDepthA,r.value.subtreeDepth=subTreeDepthB;let subTreeDepthC=this.graph.getTreeDepth(previousVertex?previousVertex.id:null,vertex.id);previousVertex&&(previousVertex.value.subtreeDepth=subTreeDepthC);let cis=0,trans=1;"C"===r.value.element&&"C"!==l.value.element&&1subTreeDepthA?(cis=1,trans=0):"C"!==r.value.element&&"C"===l.value.element&&1subTreeDepthB?(cis=0,trans=1):subTreeDepthB>subTreeDepthA&&(cis=1,trans=0);let cisVertex=this.graph.vertices[neighbours[cis]],transVertex=this.graph.vertices[neighbours[trans]],originShortest=!1;subTreeDepthCd1&&d2>d3?(s=this.graph.vertices[neighbours[1]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[2]]):d3>d1&&d3>d2&&(s=this.graph.vertices[neighbours[2]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]]),previousVertex&&1>previousVertex.value.rings.length&&1>s.value.rings.length&&1>l.value.rings.length&&1>r.value.rings.length&&1===this.graph.getTreeDepth(l.id,vertex.id)&&1===this.graph.getTreeDepth(r.id,vertex.id)&&1d1&&d2>d3&&d2>d4?(w=this.graph.vertices[neighbours[1]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[2]],z=this.graph.vertices[neighbours[3]]):d3>d1&&d3>d2&&d3>d4?(w=this.graph.vertices[neighbours[2]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[3]]):d4>d1&&d4>d2&&d4>d3&&(w=this.graph.vertices[neighbours[3]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[2]]),w.angle=-MathHelper.toRad(36),x.angle=MathHelper.toRad(36),y.angle=-MathHelper.toRad(108),z.angle=MathHelper.toRad(108),this.createNextBond(w,vertex,previousAngle+w.angle),this.createNextBond(x,vertex,previousAngle+x.angle),this.createNextBond(y,vertex,previousAngle+y.angle),this.createNextBond(z,vertex,previousAngle+z.angle)}}}getCommonRingbondNeighbour(vertex){let neighbours=vertex.neighbours;for(let i=0,neighbour;imaxLevels&&(maxLevels=priorities[j][1].length);for(let k=0;kmaxEntries&&(maxEntries=priorities[j][1][k].length)}for(let j=0,diff;jb[1][j][k])return-1;if(a[1][j][k]b[0]?-1:a[0]vertex.getNeighbourCount()||0heteroAtomCount)continue;let previous=null;for(let j=0,neighbour;jr.x+this.opts.mouseTolerance)&&(mouseY>l.y-this.opts.mouseTolerance&&mouseYr.y-this.opts.mouseTolerance&&mouseY{e.setDecay(!1)}),this.decays.forEach(e=>{this.edges[e].setDecay(!0)})}standardDecays(){for(let i=0;i{this.edges[e].setDecay(!0),this.edges[e].setDecayAll(!0),this.decays.push(e),this.decaysAll.push(e)})}isDecayPoint(sourceId,targetId,edgeBondId,decayTypes=DecayPoint.VALUES.ALL){switch(decayTypes){case DecayPoint.VALUES.ALL:let found=this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);return!1===found?this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId):found;case DecayPoint.VALUES.COO:return this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId);case DecayPoint.VALUES.CONH:return this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);}}getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"O",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"O",edgeBondId)}getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"N",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"N",edgeBondId)}getNeighbourEdgeDecayId(vertexId,element,edgeBondId){for(let i=0,edgeId;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getSubgraphDistanceMatrix(vertexIds){let length=vertexIds.length,adja=this.getSubgraphAdjacencyMatrix(vertexIds),dist=Array(length);for(var i=0;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getAdjacencyList(){let length=this.vertices.length,adjacencyList=Array(length);for(var i=0;imax&&(max=d)}return max+1}traverseTree(vertexId,parentVertexId,callback,maxDepth=999999,ignoreFirst=!1,depth=1,visited=null){if(null===visited&&(visited=new Uint8Array(this.vertices.length)),depth>maxDepth+1||1===visited[vertexId])return;visited[vertexId]=1;let vertex=this.vertices[vertexId],neighbours=vertex.getNeighbours(parentVertexId);(!ignoreFirst||1maxEnergy&&!1===arrPositioned[i]&&(maxEnergy=delta,maxEnergyId=i,maxDEX=dEX,maxDEY=dEY)}return[maxEnergyId,maxEnergy,maxDEX,maxDEY]},update=function(index,dEX,dEY){let dxx=0,dyy=0,dxy=0,ux=arrPositionX[index],uy=arrPositionY[index],arrL=matLength[index],arrK=matStrength[index];for(i=length;i--;){if(i===index)continue;let vx=arrPositionX[i],vy=arrPositionY[i],l=arrL[i],k=arrK[i],m=(ux-vx)*(ux-vx),denom=1/_Mathpow(m+(uy-vy)*(uy-vy),1.5);dxx+=k*(1-l*(uy-vy)*(uy-vy)*denom),dyy+=k*(1-l*m*denom),dxy+=k*(l*(ux-vx)*(uy-vy)*denom)}0==dxx&&(dxx=.1),0===dyy&&(dyy=.1),0===dxy&&(dxy=.1);let dy=dEX/dxx+dEY/dxy;dy/=dxy/dxx-dyy/dxy;let dx=-(dxy*dy+dEX)/dxx;arrPositionX[index]+=dx,arrPositionY[index]+=dy;let arrE=matEnergy[index];dEX=0,dEY=0,ux=arrPositionX[index],uy=arrPositionY[index];let vx,vy,prevEx,prevEy,denom;for(i=length;i--;)index!==i&&(vx=arrPositionX[i],vy=arrPositionY[i],prevEx=arrE[i][0],prevEy=arrE[i][1],denom=1/_Mathsqrt2((ux-vx)*(ux-vx)+(uy-vy)*(uy-vy)),dx=arrK[i]*(ux-vx-arrL[i]*(ux-vx)*denom),dy=arrK[i]*(uy-vy-arrL[i]*(uy-vy)*denom),arrE[i]=[dx,dy],dEX+=dx,dEY+=dy,arrEnergySumX[i]+=dx-prevEx,arrEnergySumY[i]+=dy-prevEy);arrEnergySumX[index]=dEX,arrEnergySumY[index]=dEY},maxEnergyId=0,dEX=0,dEY=0,delta=0,iteration=0,innerIteration=0;for(;maxEnergy>threshold&&maxIteration>iteration;)for(iteration++,[maxEnergyId,maxEnergy,dEX,dEY]=highestEnergy(),delta=maxEnergy,innerIteration=0;delta>innerThreshold&&maxInnerIteration>innerIteration;)innerIteration++,update(maxEnergyId,dEX,dEY),[delta,dEX,dEY]=energy(maxEnergyId);for(i=length;i--;){let index=vertexIds[i],vertex=this.vertices[index];vertex.position.x=arrPositionX[i],vertex.position.y=arrPositionY[i],vertex.positioned=!0,vertex.forcePositioned=!0}}_bridgeDfs(u,visited,disc,low,parent,adj,outBridges){visited[u]=!0,disc[u]=low[u]=++this._time;for(var i=0;idisc[u]&&outBridges.push([u,v]))}}static getConnectedComponents(adjacencyMatrix){let length=adjacencyMatrix.length,visited=Array(length),components=[],count=0;visited.fill(!1);for(var u=0;u=sequence.length)return{sequence:sequence,smiles:smiles};for(char=sequence.charAt(position);!isNaN(char);){if(number+=char,++position,position>=sequence.length)return{sequence:sequence,smiles:smiles};char=sequence.charAt(position)}let j;for(j=0;j=sequence.length)break;char=sequence.charAt(position)}return{sequence:newSequence,smiles:newSmiles}}getSequencePermutation(sequence){let match=null,permutation=[];for(;null!=(match=/\d+/g.exec(sequence));)permutation.push(match);return permutation}dfsSmallStart(){this._smallGraph=new SmallGraph;for(let index=0;indexdecaysCounter.getValue()&&!0===isPolyketide.getValue()&&isPolyketide.setValue(through.every(vertex=>"O"===vertex||"N"===vertex)&&4this.vertices[lastVertexId].digits.includes(e))&&(vertex.digits.push(this._digitCounter),this.vertices[lastVertexId].digits.push(this._digitCounter),this._digitCounter++)),vertex.vertexState===VertexState.VALUES.NOT_FOUND)&&"H"!==vertex.value.element){this.first===vertex.id&&"C"===vertex.value.element&&isPolyketide.getValue()&&(stackSmiles.push("O"),isPolyketide.setValue(!1)),vertex.value.bracket?(stackSmiles.push("["),Graph.printVertexValue(stackSmiles,vertex),0vertex.value.bracket.charge&&stackSmiles.push(vertex.value.bracket.charge),stackSmiles.push("]")):Graph.printVertexValue(stackSmiles,vertex),vertexCounter.increment(),isSecondPass&&stackSmiles.push(this.smilesNumbersAdd(vertex)),this._markComponent||this._startingVertexes.push(vertex),vertex.component=this._cnt,this._markComponent=!0,vertex.vertexState=VertexState.VALUES.OPEN;for(let i=0;i=smiles.length)););index--,numbers.add(num)}return numbers}static findFirst(smiles,number){return smiles.indexOf(number)}static findSecond(smiles,from,number){let result=smiles.indexOf(number,from);if(-1===result)throw"Not Found";return result}smilesNumbersAdd(vertex){let numbers="";for(let i=0,num;ie===num)){let nextVertex=this.vertices.find(e=>e.digits.includes(num)&&e.id!==vertex.id),intersection=vertex.edges.filter(element=>nextVertex.edges.includes(element));if(0peg$maxFailPos&&(peg$maxFailPos=peg$currPos,peg$maxFailExpected=[]),peg$maxFailExpected.push(expected))}function peg$buildSimpleError(message,location){return new peg$SyntaxError(message,null,null,location)}function peg$parsechain(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;if(s0=peg$currPos,s1=peg$currPos,s2=peg$parseatom(),s2!==peg$FAILED){for(s3=[],s4=peg$parsebranch();s4!==peg$FAILED;)s3.push(s4),s4=peg$parsebranch();if(s3!==peg$FAILED){for(s4=[],s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));s5!==peg$FAILED;)s4.push(s5),s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));if(s4!==peg$FAILED){for(s5=[],s6=peg$parsebranch();s6!==peg$FAILED;)s5.push(s6),s6=peg$parsebranch();if(s5===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s7=peg$parsechain(),s7===peg$FAILED&&(s7=null),s7!==peg$FAILED){for(s8=[],s9=peg$parsebranch();s9!==peg$FAILED;)s8.push(s9),s9=peg$parsebranch();s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8],s1=s2)}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c0(s1)),s0=s1,s0}function peg$parsebranch(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,40===input.charCodeAt(peg$currPos)?(s2="(",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c2)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parsebond(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s4=peg$parsechain(),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(41===input.charCodeAt(peg$currPos)?(s5=")",peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c4)),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5],s1=s2)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c5(s1)),s0=s1,s0}function peg$parseatom(){var s0,s1;return s0=peg$currPos,s1=peg$parseorganicsymbol(),s1===peg$FAILED&&(s1=peg$parsearomaticsymbol(),s1===peg$FAILED&&(s1=peg$parsebracketatom(),s1===peg$FAILED&&(s1=peg$parsewildcard()))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsebond(){var s0,s1;if(s0=peg$currPos,peg$c7.test(input.charAt(peg$currPos))){if(s1=input.charAt(peg$currPos),s1===input.charAt(peg$currPos+1))throw s1=peg$FAILED,peg$buildSimpleError("The parser encountered a bond repetition.",peg$currPos+1);peg$currPos++}else s1=peg$FAILED,peg$fail(peg$c8);return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c9(s1)),s0=s1,s0}function peg$parsebracketatom(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;return s0=peg$currPos,s1=peg$currPos,91===input.charCodeAt(peg$currPos)?(s2="[",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c11)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parseisotope(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):("se"===input.substr(peg$currPos,2)?(s4="se",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c13)),s4===peg$FAILED&&("as"===input.substr(peg$currPos,2)?(s4="as",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c15)),s4===peg$FAILED&&(s4=peg$parsearomaticsymbol(),s4===peg$FAILED&&(s4=peg$parseelementsymbol(),s4===peg$FAILED&&(s4=peg$parsewildcard())))),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s5=peg$parsechiral(),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s6=peg$parsehcount(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s7=peg$parsecharge(),s7===peg$FAILED&&(s7=null),s7===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s8=peg$parseclass(),s8===peg$FAILED&&(s8=null),s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(93===input.charCodeAt(peg$currPos)?(s9="]",peg$currPos++):(s9=peg$FAILED,peg$fail(peg$c17)),s9===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8,s9],s1=s2)))))))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c18(s1)),s0=s1,s0}function peg$parseorganicsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,66===input.charCodeAt(peg$currPos)?(s2="B",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c20)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(114===input.charCodeAt(peg$currPos)?(s3="r",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c22)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(s1=peg$currPos,67===input.charCodeAt(peg$currPos)?(s2="C",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c24)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(108===input.charCodeAt(peg$currPos)?(s3="l",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c26)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(peg$c27.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c28)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c29(s1)),s0=s1,s0}function peg$parsearomaticsymbol(){var s0,s1;return s0=peg$currPos,peg$c30.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c31)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsewildcard(){var s0,s1;return s0=peg$currPos,42===input.charCodeAt(peg$currPos)?(s1="*",peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c33)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c34(s1)),s0=s1,s0}function peg$parseelementsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,peg$c35.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c36)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c37.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c38)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c39(s1)),s0=s1,s0}function peg$parsering(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,37===input.charCodeAt(peg$currPos)?(s2="%",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c41)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c43)),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1===peg$FAILED&&(peg$c44.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c45))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c46(s1)),s0=s1,s0}function peg$parsechiral(){var s0,s1,s2,s3,s4,s5,s6;return s0=peg$currPos,s1=peg$currPos,64===input.charCodeAt(peg$currPos)?(s2="@",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c48)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(64===input.charCodeAt(peg$currPos)?(s3="@",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c48)),s3===peg$FAILED&&(s3=peg$currPos,"TH"===input.substr(peg$currPos,2)?(s4="TH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c50)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"AL"===input.substr(peg$currPos,2)?(s4="AL",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c54)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"SP"===input.substr(peg$currPos,2)?(s4="SP",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c56)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c57.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c58)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"TB"===input.substr(peg$currPos,2)?(s4="TB",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c60)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4))),s3===peg$FAILED&&(s3=peg$currPos,"OH"===input.substr(peg$currPos,2)?(s4="OH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c62)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4)))))))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c63(s1)),s0=s1,s0}function peg$parsecharge(){var s0,s1;return s0=peg$currPos,s1=peg$parseposcharge(),s1===peg$FAILED&&(s1=peg$parsenegcharge()),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c64(s1)),s0=s1,s0}function peg$parseposcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,43===input.charCodeAt(peg$currPos)?(s2="+",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c66)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(43===input.charCodeAt(peg$currPos)?(s3="+",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c66)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c67(s1)),s0=s1,s0}function peg$parsenegcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,45===input.charCodeAt(peg$currPos)?(s2="-",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c69)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(45===input.charCodeAt(peg$currPos)?(s3="-",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c69)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c70(s1)),s0=s1,s0}function peg$parsehcount(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,72===input.charCodeAt(peg$currPos)?(s2="H",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c72)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c73(s1)),s0=s1,s0}function peg$parseclass(){var s0,s1,s2,s3,s4,s5,s6;if(s0=peg$currPos,s1=peg$currPos,58===input.charCodeAt(peg$currPos)?(s2=":",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c75)),s2!==peg$FAILED){if(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4!==peg$FAILED){for(s5=[],peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s6!==peg$FAILED;)s5.push(s6),peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)}else peg$currPos=s3,s3=peg$FAILED;s3===peg$FAILED&&(peg$c76.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c77))),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c78(s1)),s0=s1,s0}function peg$parseisotope(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c43)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED&&(s4=null),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c79(s1)),s0=s1,s0}options=void 0===options?{}:options;var nOpenParentheses=input.split("(").length-1,nCloseParentheses=input.split(")").length-1;if(nOpenParentheses!==nCloseParentheses)throw peg$buildSimpleError("The number of opening parentheses does not match the number of closing parentheses.",0);var peg$FAILED={},peg$startRuleFunctions={chain:peg$parsechain},peg$startRuleFunction=peg$parsechain,peg$c0=function(s){for(var branches=[],rings=[],i=0;imax;){let prev=current;callback(prev),current=vertices[current].getNextInRing(vertices,this.id,previousVertexId),previousVertexId=prev,current==startVertexId&&(current=null),max++}}getOrderedNeighbours(ringConnections){let orderedNeighbours=Array(this.neighbours.length);for(let i=0,vertices;inewPathLength){var l,m,n;if(previousPathLength===newPathLength+1)for(pe_prime[i][j]=[pe[i][j].length],l=pe[i][j].length;l--;)for(pe_prime[i][j][l]=[pe[i][j][l].length],m=pe[i][j][l].length;m--;)for(pe_prime[i][j][l][m]=[pe[i][j][l][m].length],n=pe[i][j][l][m].length;n--;)pe_prime[i][j][l][m][n]=[pe[i][j][l][m][0],pe[i][j][l][m][1]];else pe_prime[i][j]=[];for(d[i][j]=newPathLength,pe[i][j]=[[]],l=pe[i][k][0].length;l--;)pe[i][j][0].push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)pe[i][j][0].push(pe[k][j][0][l])}else if(previousPathLength===newPathLength){if(pe[i][k].length&&pe[k][j].length){var l;if(pe[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j][0]=tmp}}}else if(previousPathLength===newPathLength-1){var l;if(pe_prime[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j][0]=tmp}}}return{d:d,pe:pe,pe_prime:pe_prime}}static getRingCandidates(d,pe,pe_prime){let length=d.length,candidates=[],c=0;for(let i=0;insssr)return cSssr}else for(let j=0,bonds;jnsssr)return cSssr}return cSssr}static getEdgeCount(adjacencyMatrix){let edgeCount=0,length=adjacencyMatrix.length;for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeCount++;return edgeCount}static getEdgeList(adjacencyMatrix){let length=adjacencyMatrix.length,edgeList=[];for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeList.push([i,j]);return edgeList}static bondsToAtoms(bonds){let atoms=new Set;for(var i=bonds.length;i--;)atoms.add(bonds[i][0]),atoms.add(bonds[i][1]);return atoms}static getBondCount(atoms,adjacencyMatrix){let count=0;for(let u of atoms)for(let v of atoms)u!==v&&(count+=adjacencyMatrix[u][v]);return count/2}static pathSetsContain(pathSets,pathSet,bonds,allBonds,arrBondCount,arrRingCount){for(var i=pathSets.length;i--;){if(SSSR.isSupersetOf(pathSet,pathSets[i]))return!0;if(pathSets[i].size===pathSet.size&&SSSR.areSetsEqual(pathSets[i],pathSet))return!0}let count=0,allContained=!1;for(i=bonds.length;i--;)for(var j=allBonds.length;j--;)(bonds[i][0]===allBonds[j][0]&&bonds[i][1]===allBonds[j][1]||bonds[i][1]===allBonds[j][0]&&bonds[i][0]===allBonds[j][1])&&count++,count===bonds.length&&(allContained=!0);let specialCase=!1;if(allContained)for(let element of pathSet)if(arrRingCount[element]e.vertexState=VertexState.VALUES.NOT_FOUND)}getSourceNode(){let ends=[];for(let index=0;indexthis._nodes[v].onRing=!0);continue}node.neighbours.forEach(neighbour=>{if(!path.some(e=>e===neighbour.neighbour)||neighbour.neighbour===start.id){let newPath=[...path];newPath.push(neighbour.neighbour),queue.push(newPath)}}),firstPass=!1}}sortByRingPreference(array){let sortedArray=[...array];return sortedArray.sort((a,b)=>this._nodes[a.neighbour].onRing===this._nodes[b.neighbour].onRing?a.direction>b.direction?-1:a.direction{let edges=graph.getEdges(vertex.id);for(var i=0;is.sideCount[1]||s.totalSideCount[0]>s.totalSideCount[1]){this.multiplyNormals(normals,opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB);line.shorten(opts.bondLength-opts.shortBondLength*opts.bondLength),svgWrapper.drawLine(line),svgWrapper.drawLine(new Line(a,b,elementA,elementB))}else if(s.sideCount[0]_Mathabs2(_MathPI3-angle)&&svgWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,vertex.value.chirality)}if(opts.debug)for(var i=0;i{const context=canvas.getContext("2d");context.clearRect(0,0,canvas.width,canvas.height)})},SmilesDrawer.parse=function(smiles,successCallback,errorCallback){try{successCallback&&successCallback(Parser.parse(smiles))}catch(err){errorCallback&&errorCallback(err)}},canUseDOM&&(window.SmilesDrawer=SmilesDrawer),Array.prototype.fill||Object.defineProperty(Array.prototype,"fill",{value:function(value){if(null==this)throw new TypeError("this is null or not defined");for(var O=Object(this),len=O.length>>>0,start=arguments[1],relativeStart=start>>0,k=0>relativeStart?_Mathmax(len+relativeStart,0):_Mathmin(relativeStart,len),end=arguments[2],relativeEnd=void 0===end?len:end>>0,final=0>relativeEnd?_Mathmax(len+relativeEnd,0):_Mathmin(relativeEnd,len);kp.x&&(minX=p.x),minY>p.y&&(minY=p.y)}var padding=this.opts.padding;maxX+=padding,maxY+=padding,minX-=padding,minY-=padding,this.drawingWidth=maxX-minX,this.drawingHeight=maxY-minY;var scaleX=this.canvas.offsetWidth/this.drawingWidth,scaleY=this.canvas.offsetHeight/this.drawingHeight,scale=scaleXalpha&&(ctx.globalAlpha=alpha),ctx.strokeStyle=gradient,ctx.stroke(),ctx.restore()}drawWedge(line,width=1){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,shortLine=line.clone().shorten(5),l=shortLine.getLeftVector().clone(),r=shortLine.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone(),l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),start=l,end=r;isRightChiralCenter&&(start=r,end=l);let t=Vector2.add(start,Vector2.multiplyScalar(normals[0],this.halfBondThickness)),u=Vector2.add(end,Vector2.multiplyScalar(normals[0],1.5+this.halfBondThickness)),v=Vector2.add(end,Vector2.multiplyScalar(normals[1],1.5+this.halfBondThickness)),w=Vector2.add(start,Vector2.multiplyScalar(normals[1],this.halfBondThickness));ctx.beginPath(),ctx.moveTo(t.x,t.y),ctx.lineTo(u.x,u.y),ctx.lineTo(v.x,v.y),ctx.lineTo(w.x,w.y);let gradient=this.ctx.createRadialGradient(r.x,r.y,this.opts.bondLength,r.x,r.y,0);gradient.addColorStop(.4,this.themeManager.getColor(line.getLeftElement())||this.themeManager.getColor("C")),gradient.addColorStop(.6,this.themeManager.getColor(line.getRightElement())||this.themeManager.getColor("C")),ctx.fillStyle=gradient,ctx.fill(),ctx.restore()}drawDashedWedge(line){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),shortLine=line.clone(),start,end,sStart,sEnd;isRightChiralCenter?(start=r,end=l,shortLine.shortenRight(1),sStart=shortLine.getRightVector().clone(),sEnd=shortLine.getLeftVector().clone()):(start=l,end=r,shortLine.shortenLeft(1),sStart=shortLine.getLeftVector().clone(),sEnd=shortLine.getRightVector().clone()),sStart.x+=offsetX,sStart.y+=offsetY,sEnd.x+=offsetX,sEnd.y+=offsetY;let dir=Vector2.subtract(end,start).normalize();ctx.strokeStyle=this.themeManager.getColor("C"),ctx.lineCap="round",ctx.lineWidth=this.opts.bondThickness,ctx.beginPath();let length=line.getLength(),step=1.25/(length/(3*this.opts.bondThickness)),changed=!1;for(var t=0;1>t;t+=step){let to=Vector2.multiplyScalar(dir,t*length),startDash=Vector2.add(start,to),width=1.5*t,dashOffset=Vector2.multiplyScalar(normals[0],width);!changed&&.5this.opts.fontSizeLarge?dim.width:this.opts.fontSizeLarge;r/=1.5,ctx.globalCompositeOperation="destination-out",ctx.beginPath(),ctx.arc(x+offsetX,y+offsetY,r,0,MathHelper.twoPI,!0),ctx.closePath(),ctx.fill(),ctx.globalCompositeOperation="source-over";let cursorPos=-dim.width/2,cursorPosLeft=-dim.width/2;ctx.fillStyle=this.themeManager.getColor(elementName),ctx.fillText(elementName,x+offsetX+cursorPos,y+this.opts.halfFontSizeLarge+offsetY),cursorPos+=dim.width,charge&&(ctx.font=this.fontSmall,ctx.fillText(chargeText,x+offsetX+cursorPos,y-this.opts.fifthFontSizeSmall+offsetY),cursorPos+=chargeWidth),0maxDist&&(maxDist=dist,a=i,b=j)}let angle=-Vector2.subtract(this.graph.vertices[a].position,this.graph.vertices[b].position).angle();if(!isNaN(angle)){let remainder=angle%.523599;.2617995>remainder?angle-=remainder:angle+=.523599-remainder;for(let i=0;i{if(counts.has(e)){let count=counts.get(e);molecularFormula+=e+(1vertexA.value.getRingbondCount()||1>vertexB.value.getRingbondCount())return null;for(var i=0;isubTreeDepthB&&(a=edge.sourceId,b=edge.targetId);let subTreeOverlap=this.getSubtreeOverlapScore(b,a,overlapScore.vertexScores);if(subTreeOverlap.value>this.opts.overlapSensitivity){let vertexA=this.graph.vertices[a],vertexB=this.graph.vertices[b],neighboursB=vertexB.getNeighbours(a);if(1===neighboursB.length){let neighbour=this.graph.vertices[neighboursB[0]],angle=neighbour.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbour.id,vertexB.id,angle,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?this.rotateSubtree(neighbour.id,vertexB.id,-angle,vertexB.position):this.totalOverlapScore=newTotalOverlapScore}else if(2===neighboursB.length){if(0!==vertexB.value.rings.length&&0!==vertexA.value.rings.length)continue;let neighbourA=this.graph.vertices[neighboursB[0]],neighbourB=this.graph.vertices[neighboursB[1]];if(1===neighbourA.value.rings.length&&1===neighbourB.value.rings.length){if(neighbourA.value.rings[0]!==neighbourB.value.rings[0])continue;}else if(0!==neighbourA.value.rings.length||0!==neighbourB.value.rings.length)continue;else{let angleA=neighbourA.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120)),angleB=neighbourB.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbourA.id,vertexB.id,angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,angleB,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?(this.rotateSubtree(neighbourA.id,vertexB.id,-angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,-angleB,vertexB.position)):this.totalOverlapScore=newTotalOverlapScore}}overlapScore=this.getOverlapScore()}}}this.resolveSecondaryOverlaps(overlapScore.scores),this.opts.isomeric&&this.annotateStereochemistry(),this.opts.compactDrawing&&"default"===this.opts.atomVisualization&&this.initPseudoElements(),this.rotateDrawing()}initRings(){let openBonds=new Map;for(let i=this.graph.vertices.length-1,vertex;0<=i;i--)if(vertex=this.graph.vertices[i],0!==vertex.value.ringbonds.length)for(let j=0;jneighbour.value.rings.length&&!neighbour.value.bridgedRing||neighbour.value.bridgedRing&&2>neighbour.value.originalRings.length)&&(vertex.value.isDrawn=!1)}}getBridgedRingRings(ringId){let involvedRings=[],that=this,recurse=function(r){let ring=that.getRing(r);involvedRings.push(r);for(let i=0,n;imaxSize&&(maxSize=size,largestCommonRing=ring)}return largestCommonRing}getVerticesAt(position,radius,excludeVertexId){let locals=[];for(let i=0,vertex;ii;){let a=this.graph.vertices[i],b=this.graph.vertices[j];if(!a.value.isDrawn||!b.value.isDrawn)continue;let dist=Vector2.subtract(a.position,b.position).lengthSq();if(disttotalSideCount[1]?0:1,sideCount:sideCount,position:sideCount[0]>sideCount[1]?0:1,anCount:anCount,bnCount:bnCount}}setRingCenter(ring){let ringSize=ring.getSize(),total=new Vector2(0,0);for(let i=0;is.sideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.sideCount[0]s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.totalSideCount[0]<=s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}}else if("#"===edge.bondType){normals[0].multiplyScalar(that.opts.bondSpacing/1.5),normals[1].multiplyScalar(that.opts.bondSpacing/1.5);let lineA=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)),lineB=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));this.canvasWrapper.drawLine(lineA),this.canvasWrapper.drawLine(lineB),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if("."===edge.bondType);else{let isChiralCenterA=vertexA.value.isStereoCenter,isChiralCenterB=vertexB.value.isStereoCenter;"up"===edge.wedge?this.canvasWrapper.drawWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):"down"===edge.wedge?this.canvasWrapper.drawDashedWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay)))}if(debug){let midpoint=Vector2.midpoint(a,b);this.canvasWrapper.drawDebugText(midpoint.x,midpoint.y,"e: "+edgeId)}}drawVertices(debug){for(let i=0;i_Mathabs(_MathPI-angle)&&this.canvasWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);this.canvasWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else;}if(this.opts.debug)for(let i=0,center;iring.rings.length)&&(vertex.angle=a,vertex.positioned=!0)},startVertexId,previousVertex?previousVertex.id:null);ring.positioned=!0,ring.center=center;for(let i=0,neighbour;iVector2.subtract(center,normals[0]).lengthSq()&&(nextCenter=normals[1]);let posA=Vector2.subtract(vertexA.position,nextCenter),posB=Vector2.subtract(vertexB.position,nextCenter);-1===posA.clockwise(posB)?!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexA,vertexB):!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexB,vertexA)}else if(1===vertices.length){ring.isSpiro=!0,neighbour.isSpiro=!0;let vertexA=this.graph.vertices[vertices[0]],nextCenter=Vector2.subtract(center,vertexA.position);nextCenter.invert(),nextCenter.normalize();let r=MathHelper.polyCircumradius(this.opts.bondLength,neighbour.getSize());nextCenter.multiplyScalar(r),nextCenter.add(vertexA.position),neighbour.positioned||this.createRing(neighbour,nextCenter,vertexA)}}for(let i=0;ithat.opts.overlapSensitivity&&(score+=s,count++);let position=that.graph.vertices[vertex.id].position.clone();position.multiplyScalar(s),center.add(position)}}),center.divide(score),{value:score/count,center:center}}getCurrentCenterOfMass(){let total=new Vector2(0,0),count=0;for(let i=0,vertex;itotal&&(this.rotateSubtree(a.id,overlap.common.id,2*angle,overlap.common.position),this.rotateSubtree(b.id,overlap.common.id,-2*angle,overlap.common.position))}else 1!==overlap.vertices.length||2!==overlap.rings.length}resolveSecondaryOverlaps(scores){for(let i=0;ithis.opts.overlapSensitivity){let vertex=this.graph.vertices[scores[i].id];if(vertex.isTerminal()){let closest=this.getClosestVertex(vertex);if(closest){let closestPosition=null;closestPosition=closest.isTerminal()?0===closest.id?this.graph.vertices[1].position:closest.previousPosition:0===closest.id?this.graph.vertices[1].position:closest.position;let vertexPreviousPosition=0===vertex.id?this.graph.vertices[1].position:vertex.previousPosition;vertex.position.rotateAwayFrom(closestPosition,vertexPreviousPosition,MathHelper.toRad(20))}}}}getLastVertexWithAngle(vertexId){let angle=0,vertex=null;for(;!angle&&vertexId;)vertex=this.graph.vertices[vertexId],angle=vertex.angle,vertexId=vertex.parentVertexId;return vertex}createNextBond(vertex,previousVertex=null,angle=0,originShortest=!1,skipPositioning=!1){if(vertex.positioned&&!skipPositioning)return;let doubleBondConfigSet=!1;if(previousVertex){let edge=this.graph.getEdge(vertex.id,previousVertex.id);("/"===edge.bondType||"\\"===edge.bondType)&&1==++this.doubleBondConfigCount%2&&null===this.doubleBondConfig&&(this.doubleBondConfig=edge.bondType,doubleBondConfigSet=!0,null===previousVertex.parentVertexId&&vertex.value.branchBond&&("/"===this.doubleBondConfig?this.doubleBondConfig="\\":"\\"===this.doubleBondConfig&&(this.doubleBondConfig="/")))}if(!skipPositioning)if(!previousVertex){let dummy=new Vector2(this.opts.bondLength,0);dummy.rotate(MathHelper.toRad(-60)),vertex.previousPosition=dummy,vertex.setPosition(this.opts.bondLength,0),vertex.angle=MathHelper.toRad(-60),null===vertex.value.bridgedRing&&(vertex.positioned=!0)}else if(0a?_Mathmax2(-1.0472,a):1.0472;else if(!a){let v=this.getLastVertexWithAngle(vertex.id);a=v.angle,a||(a=1.0472)}if(previousVertex&&!doubleBondConfigSet){let bondType=this.graph.getEdge(vertex.id,nextVertex.id).bondType;"/"===bondType?("/"===this.doubleBondConfig||"\\"===this.doubleBondConfig&&(a=-a),this.doubleBondConfig=null):"\\"===bondType&&("/"===this.doubleBondConfig?a=-a:"\\"===this.doubleBondConfig,this.doubleBondConfig=null)}nextVertex.angle=originShortest?a:-a,this.createNextBond(nextVertex,vertex,previousAngle+nextVertex.angle)}}else if(2===neighbours.length){let a=vertex.angle;a||(a=1.0472);let subTreeDepthA=this.graph.getTreeDepth(neighbours[0],vertex.id),subTreeDepthB=this.graph.getTreeDepth(neighbours[1],vertex.id),l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]];l.value.subtreeDepth=subTreeDepthA,r.value.subtreeDepth=subTreeDepthB;let subTreeDepthC=this.graph.getTreeDepth(previousVertex?previousVertex.id:null,vertex.id);previousVertex&&(previousVertex.value.subtreeDepth=subTreeDepthC);let cis=0,trans=1;"C"===r.value.element&&"C"!==l.value.element&&1subTreeDepthA?(cis=1,trans=0):"C"!==r.value.element&&"C"===l.value.element&&1subTreeDepthB?(cis=0,trans=1):subTreeDepthB>subTreeDepthA&&(cis=1,trans=0);let cisVertex=this.graph.vertices[neighbours[cis]],transVertex=this.graph.vertices[neighbours[trans]],originShortest=!1;subTreeDepthCd1&&d2>d3?(s=this.graph.vertices[neighbours[1]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[2]]):d3>d1&&d3>d2&&(s=this.graph.vertices[neighbours[2]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]]),previousVertex&&1>previousVertex.value.rings.length&&1>s.value.rings.length&&1>l.value.rings.length&&1>r.value.rings.length&&1===this.graph.getTreeDepth(l.id,vertex.id)&&1===this.graph.getTreeDepth(r.id,vertex.id)&&1d1&&d2>d3&&d2>d4?(w=this.graph.vertices[neighbours[1]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[2]],z=this.graph.vertices[neighbours[3]]):d3>d1&&d3>d2&&d3>d4?(w=this.graph.vertices[neighbours[2]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[3]]):d4>d1&&d4>d2&&d4>d3&&(w=this.graph.vertices[neighbours[3]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[2]]),w.angle=-MathHelper.toRad(36),x.angle=MathHelper.toRad(36),y.angle=-MathHelper.toRad(108),z.angle=MathHelper.toRad(108),this.createNextBond(w,vertex,previousAngle+w.angle),this.createNextBond(x,vertex,previousAngle+x.angle),this.createNextBond(y,vertex,previousAngle+y.angle),this.createNextBond(z,vertex,previousAngle+z.angle)}}}getCommonRingbondNeighbour(vertex){let neighbours=vertex.neighbours;for(let i=0,neighbour;imaxLevels&&(maxLevels=priorities[j][1].length);for(let k=0;kmaxEntries&&(maxEntries=priorities[j][1][k].length)}for(let j=0,diff;jb[1][j][k])return-1;if(a[1][j][k]b[0]?-1:a[0]vertex.getNeighbourCount()||0heteroAtomCount)continue;let previous=null;for(let j=0,neighbour;jr.x+this.opts.mouseTolerance)&&(mouseY>l.y-this.opts.mouseTolerance&&mouseYr.y-this.opts.mouseTolerance&&mouseY{e.setDecay(!1)}),this.decays.forEach(e=>{this.edges[e].setDecay(!0)})}standardDecays(){for(let i=0;i{this.edges[e].setDecay(!0),this.edges[e].setDecayAll(!0),this.decays.push(e),this.decaysAll.push(e)})}isDecayPoint(sourceId,targetId,edgeBondId,decayTypes=DecayPoint.VALUES.ALL){switch(decayTypes){case DecayPoint.VALUES.ALL:let found=this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);return!1===found?this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId):found;case DecayPoint.VALUES.COO:return this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId);case DecayPoint.VALUES.CONH:return this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);}}getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"O",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"O",edgeBondId)}getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"N",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"N",edgeBondId)}getNeighbourEdgeDecayId(vertexId,element,edgeBondId){for(let i=0,edgeId;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getSubgraphDistanceMatrix(vertexIds){let length=vertexIds.length,adja=this.getSubgraphAdjacencyMatrix(vertexIds),dist=Array(length);for(var i=0;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getAdjacencyList(){let length=this.vertices.length,adjacencyList=Array(length);for(var i=0;imax&&(max=d)}return max+1}traverseTree(vertexId,parentVertexId,callback,maxDepth=999999,ignoreFirst=!1,depth=1,visited=null){if(null===visited&&(visited=new Uint8Array(this.vertices.length)),depth>maxDepth+1||1===visited[vertexId])return;visited[vertexId]=1;let vertex=this.vertices[vertexId],neighbours=vertex.getNeighbours(parentVertexId);(!ignoreFirst||1maxEnergy&&!1===arrPositioned[i]&&(maxEnergy=delta,maxEnergyId=i,maxDEX=dEX,maxDEY=dEY)}return[maxEnergyId,maxEnergy,maxDEX,maxDEY]},update=function(index,dEX,dEY){let dxx=0,dyy=0,dxy=0,ux=arrPositionX[index],uy=arrPositionY[index],arrL=matLength[index],arrK=matStrength[index];for(i=length;i--;){if(i===index)continue;let vx=arrPositionX[i],vy=arrPositionY[i],l=arrL[i],k=arrK[i],m=(ux-vx)*(ux-vx),denom=1/_Mathpow(m+(uy-vy)*(uy-vy),1.5);dxx+=k*(1-l*(uy-vy)*(uy-vy)*denom),dyy+=k*(1-l*m*denom),dxy+=k*(l*(ux-vx)*(uy-vy)*denom)}0==dxx&&(dxx=.1),0===dyy&&(dyy=.1),0===dxy&&(dxy=.1);let dy=dEX/dxx+dEY/dxy;dy/=dxy/dxx-dyy/dxy;let dx=-(dxy*dy+dEX)/dxx;arrPositionX[index]+=dx,arrPositionY[index]+=dy;let arrE=matEnergy[index];dEX=0,dEY=0,ux=arrPositionX[index],uy=arrPositionY[index];let vx,vy,prevEx,prevEy,denom;for(i=length;i--;)index!==i&&(vx=arrPositionX[i],vy=arrPositionY[i],prevEx=arrE[i][0],prevEy=arrE[i][1],denom=1/_Mathsqrt2((ux-vx)*(ux-vx)+(uy-vy)*(uy-vy)),dx=arrK[i]*(ux-vx-arrL[i]*(ux-vx)*denom),dy=arrK[i]*(uy-vy-arrL[i]*(uy-vy)*denom),arrE[i]=[dx,dy],dEX+=dx,dEY+=dy,arrEnergySumX[i]+=dx-prevEx,arrEnergySumY[i]+=dy-prevEy);arrEnergySumX[index]=dEX,arrEnergySumY[index]=dEY},maxEnergyId=0,dEX=0,dEY=0,delta=0,iteration=0,innerIteration=0;for(;maxEnergy>threshold&&maxIteration>iteration;)for(iteration++,[maxEnergyId,maxEnergy,dEX,dEY]=highestEnergy(),delta=maxEnergy,innerIteration=0;delta>innerThreshold&&maxInnerIteration>innerIteration;)innerIteration++,update(maxEnergyId,dEX,dEY),[delta,dEX,dEY]=energy(maxEnergyId);for(i=length;i--;){let index=vertexIds[i],vertex=this.vertices[index];vertex.position.x=arrPositionX[i],vertex.position.y=arrPositionY[i],vertex.positioned=!0,vertex.forcePositioned=!0}}_bridgeDfs(u,visited,disc,low,parent,adj,outBridges){visited[u]=!0,disc[u]=low[u]=++this._time;for(var i=0;idisc[u]&&outBridges.push([u,v]))}}static getConnectedComponents(adjacencyMatrix){let length=adjacencyMatrix.length,visited=Array(length),components=[],count=0;visited.fill(!1);for(var u=0;u=sequence.length)return{sequence:sequence,smiles:smiles};for(char=sequence.charAt(position);!isNaN(char);){if(number+=char,++position,position>=sequence.length)return{sequence:sequence,smiles:smiles};char=sequence.charAt(position)}let j;for(j=0;j=sequence.length)break;char=sequence.charAt(position)}return{sequence:newSequence,smiles:newSmiles}}getSequencePermutation(sequence){let match=null,permutation=[];for(;null!=(match=/\d+/g.exec(sequence));)permutation.push(match);return permutation}dfsSmallStart(){this._smallGraph=new SmallGraph;for(let index=0;indexdecaysCounter.getValue()&&!0===isPolyketide.getValue()&&isPolyketide.setValue(through.every(vertex=>"O"===vertex||"N"===vertex)&&4this.vertices[lastVertexId].digits.includes(e))&&(vertex.digits.push(this._digitCounter),this.vertices[lastVertexId].digits.push(this._digitCounter),this._digitCounter++)),vertex.vertexState===VertexState.VALUES.NOT_FOUND)&&"H"!==vertex.value.element){this.first===vertex.id&&"C"===vertex.value.element&&isPolyketide.getValue()&&(stackSmiles.push("O"),isPolyketide.setValue(!1)),vertex.value.bracket?(stackSmiles.push("["),Graph.printVertexValue(stackSmiles,vertex),0vertex.value.bracket.charge&&stackSmiles.push(vertex.value.bracket.charge),stackSmiles.push("]")):Graph.printVertexValue(stackSmiles,vertex),vertexCounter.increment(),isSecondPass&&stackSmiles.push(this.smilesNumbersAdd(vertex)),this._markComponent||this._startingVertexes.push(vertex),vertex.component=this._cnt,this._markComponent=!0,vertex.vertexState=VertexState.VALUES.OPEN;for(let i=0;i=smiles.length)););index--,numbers.add(num)}return numbers}static findFirst(smiles,number){return smiles.indexOf(number)}static findSecond(smiles,from,number){let result=smiles.indexOf(number,from);if(-1===result)throw"Not Found";return result}smilesNumbersAdd(vertex){let numbers="";for(let i=0,num;ie===num)){let nextVertex=this.vertices.find(e=>e.digits.includes(num)&&e.id!==vertex.id),intersection=vertex.edges.filter(element=>nextVertex.edges.includes(element));if(0peg$maxFailPos&&(peg$maxFailPos=peg$currPos,peg$maxFailExpected=[]),peg$maxFailExpected.push(expected))}function peg$buildSimpleError(message,location){return new peg$SyntaxError(message,null,null,location)}function peg$parsechain(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;if(s0=peg$currPos,s1=peg$currPos,s2=peg$parseatom(),s2!==peg$FAILED){for(s3=[],s4=peg$parsebranch();s4!==peg$FAILED;)s3.push(s4),s4=peg$parsebranch();if(s3!==peg$FAILED){for(s4=[],s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));s5!==peg$FAILED;)s4.push(s5),s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));if(s4!==peg$FAILED){for(s5=[],s6=peg$parsebranch();s6!==peg$FAILED;)s5.push(s6),s6=peg$parsebranch();if(s5===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s7=peg$parsechain(),s7===peg$FAILED&&(s7=null),s7!==peg$FAILED){for(s8=[],s9=peg$parsebranch();s9!==peg$FAILED;)s8.push(s9),s9=peg$parsebranch();s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8],s1=s2)}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c0(s1)),s0=s1,s0}function peg$parsebranch(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,40===input.charCodeAt(peg$currPos)?(s2="(",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c2)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parsebond(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s4=peg$parsechain(),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(41===input.charCodeAt(peg$currPos)?(s5=")",peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c4)),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5],s1=s2)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c5(s1)),s0=s1,s0}function peg$parseatom(){var s0,s1;return s0=peg$currPos,s1=peg$parseorganicsymbol(),s1===peg$FAILED&&(s1=peg$parsearomaticsymbol(),s1===peg$FAILED&&(s1=peg$parsebracketatom(),s1===peg$FAILED&&(s1=peg$parsewildcard()))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsebond(){var s0,s1;if(s0=peg$currPos,peg$c7.test(input.charAt(peg$currPos))){if(s1=input.charAt(peg$currPos),s1===input.charAt(peg$currPos+1))throw s1=peg$FAILED,peg$buildSimpleError("The parser encountered a bond repetition.",peg$currPos+1);peg$currPos++}else s1=peg$FAILED,peg$fail(peg$c8);return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c9(s1)),s0=s1,s0}function peg$parsebracketatom(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;return s0=peg$currPos,s1=peg$currPos,91===input.charCodeAt(peg$currPos)?(s2="[",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c11)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parseisotope(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):("se"===input.substr(peg$currPos,2)?(s4="se",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c13)),s4===peg$FAILED&&("as"===input.substr(peg$currPos,2)?(s4="as",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c15)),s4===peg$FAILED&&(s4=peg$parsearomaticsymbol(),s4===peg$FAILED&&(s4=peg$parseelementsymbol(),s4===peg$FAILED&&(s4=peg$parsewildcard())))),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s5=peg$parsechiral(),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s6=peg$parsehcount(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s7=peg$parsecharge(),s7===peg$FAILED&&(s7=null),s7===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s8=peg$parseclass(),s8===peg$FAILED&&(s8=null),s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(93===input.charCodeAt(peg$currPos)?(s9="]",peg$currPos++):(s9=peg$FAILED,peg$fail(peg$c17)),s9===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8,s9],s1=s2)))))))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c18(s1)),s0=s1,s0}function peg$parseorganicsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,66===input.charCodeAt(peg$currPos)?(s2="B",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c20)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(114===input.charCodeAt(peg$currPos)?(s3="r",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c22)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(s1=peg$currPos,67===input.charCodeAt(peg$currPos)?(s2="C",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c24)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(108===input.charCodeAt(peg$currPos)?(s3="l",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c26)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(peg$c27.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c28)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c29(s1)),s0=s1,s0}function peg$parsearomaticsymbol(){var s0,s1;return s0=peg$currPos,peg$c30.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c31)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsewildcard(){var s0,s1;return s0=peg$currPos,42===input.charCodeAt(peg$currPos)?(s1="*",peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c33)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c34(s1)),s0=s1,s0}function peg$parseelementsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,peg$c35.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c36)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c37.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c38)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c39(s1)),s0=s1,s0}function peg$parsering(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,37===input.charCodeAt(peg$currPos)?(s2="%",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c41)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c43)),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1===peg$FAILED&&(peg$c44.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c45))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c46(s1)),s0=s1,s0}function peg$parsechiral(){var s0,s1,s2,s3,s4,s5,s6;return s0=peg$currPos,s1=peg$currPos,64===input.charCodeAt(peg$currPos)?(s2="@",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c48)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(64===input.charCodeAt(peg$currPos)?(s3="@",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c48)),s3===peg$FAILED&&(s3=peg$currPos,"TH"===input.substr(peg$currPos,2)?(s4="TH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c50)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"AL"===input.substr(peg$currPos,2)?(s4="AL",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c54)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"SP"===input.substr(peg$currPos,2)?(s4="SP",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c56)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c57.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c58)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"TB"===input.substr(peg$currPos,2)?(s4="TB",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c60)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4))),s3===peg$FAILED&&(s3=peg$currPos,"OH"===input.substr(peg$currPos,2)?(s4="OH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c62)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4)))))))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c63(s1)),s0=s1,s0}function peg$parsecharge(){var s0,s1;return s0=peg$currPos,s1=peg$parseposcharge(),s1===peg$FAILED&&(s1=peg$parsenegcharge()),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c64(s1)),s0=s1,s0}function peg$parseposcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,43===input.charCodeAt(peg$currPos)?(s2="+",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c66)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(43===input.charCodeAt(peg$currPos)?(s3="+",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c66)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c67(s1)),s0=s1,s0}function peg$parsenegcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,45===input.charCodeAt(peg$currPos)?(s2="-",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c69)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(45===input.charCodeAt(peg$currPos)?(s3="-",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c69)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c70(s1)),s0=s1,s0}function peg$parsehcount(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,72===input.charCodeAt(peg$currPos)?(s2="H",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c72)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c73(s1)),s0=s1,s0}function peg$parseclass(){var s0,s1,s2,s3,s4,s5,s6;if(s0=peg$currPos,s1=peg$currPos,58===input.charCodeAt(peg$currPos)?(s2=":",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c75)),s2!==peg$FAILED){if(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4!==peg$FAILED){for(s5=[],peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s6!==peg$FAILED;)s5.push(s6),peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)}else peg$currPos=s3,s3=peg$FAILED;s3===peg$FAILED&&(peg$c76.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c77))),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c78(s1)),s0=s1,s0}function peg$parseisotope(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c43)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED&&(s4=null),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c79(s1)),s0=s1,s0}options=void 0===options?{}:options;var nOpenParentheses=input.split("(").length-1,nCloseParentheses=input.split(")").length-1;if(nOpenParentheses!==nCloseParentheses)throw peg$buildSimpleError("The number of opening parentheses does not match the number of closing parentheses.",0);var peg$FAILED={},peg$startRuleFunctions={chain:peg$parsechain},peg$startRuleFunction=peg$parsechain,peg$c0=function(s){for(var branches=[],rings=[],i=0;imax;){let prev=current;callback(prev),current=vertices[current].getNextInRing(vertices,this.id,previousVertexId),previousVertexId=prev,current==startVertexId&&(current=null),max++}}getOrderedNeighbours(ringConnections){let orderedNeighbours=Array(this.neighbours.length);for(let i=0,vertices;inewPathLength){var l,m,n;if(previousPathLength===newPathLength+1)for(pe_prime[i][j]=[pe[i][j].length],l=pe[i][j].length;l--;)for(pe_prime[i][j][l]=[pe[i][j][l].length],m=pe[i][j][l].length;m--;)for(pe_prime[i][j][l][m]=[pe[i][j][l][m].length],n=pe[i][j][l][m].length;n--;)pe_prime[i][j][l][m][n]=[pe[i][j][l][m][0],pe[i][j][l][m][1]];else pe_prime[i][j]=[];for(d[i][j]=newPathLength,pe[i][j]=[[]],l=pe[i][k][0].length;l--;)pe[i][j][0].push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)pe[i][j][0].push(pe[k][j][0][l])}else if(previousPathLength===newPathLength){if(pe[i][k].length&&pe[k][j].length){var l;if(pe[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j][0]=tmp}}}else if(previousPathLength===newPathLength-1){var l;if(pe_prime[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j][0]=tmp}}}return{d:d,pe:pe,pe_prime:pe_prime}}static getRingCandidates(d,pe,pe_prime){let length=d.length,candidates=[],c=0;for(let i=0;insssr)return cSssr}else for(let j=0,bonds;jnsssr)return cSssr}return cSssr}static getEdgeCount(adjacencyMatrix){let edgeCount=0,length=adjacencyMatrix.length;for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeCount++;return edgeCount}static getEdgeList(adjacencyMatrix){let length=adjacencyMatrix.length,edgeList=[];for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeList.push([i,j]);return edgeList}static bondsToAtoms(bonds){let atoms=new Set;for(var i=bonds.length;i--;)atoms.add(bonds[i][0]),atoms.add(bonds[i][1]);return atoms}static getBondCount(atoms,adjacencyMatrix){let count=0;for(let u of atoms)for(let v of atoms)u!==v&&(count+=adjacencyMatrix[u][v]);return count/2}static pathSetsContain(pathSets,pathSet,bonds,allBonds,arrBondCount,arrRingCount){for(var i=pathSets.length;i--;){if(SSSR.isSupersetOf(pathSet,pathSets[i]))return!0;if(pathSets[i].size===pathSet.size&&SSSR.areSetsEqual(pathSets[i],pathSet))return!0}let count=0,allContained=!1;for(i=bonds.length;i--;)for(var j=allBonds.length;j--;)(bonds[i][0]===allBonds[j][0]&&bonds[i][1]===allBonds[j][1]||bonds[i][1]===allBonds[j][0]&&bonds[i][0]===allBonds[j][1])&&count++,count===bonds.length&&(allContained=!0);let specialCase=!1;if(allContained)for(let element of pathSet)if(arrRingCount[element]e.vertexState=VertexState.VALUES.NOT_FOUND)}getSourceNode(){let ends=[];for(let index=0;indexthis._nodes[v].onRing=!0);continue}node.neighbours.forEach(neighbour=>{if(!path.some(e=>e===neighbour.neighbour)||neighbour.neighbour===start.id){let newPath=[...path];newPath.push(neighbour.neighbour),queue.push(newPath)}}),firstPass=!1}}sortByRingPreference(array){let sortedArray=[...array];return sortedArray.sort((a,b)=>this._nodes[a.neighbour].onRing===this._nodes[b.neighbour].onRing?a.direction>b.direction?-1:a.direction{let edges=graph.getEdges(vertex.id);for(var i=0;is.sideCount[1]||s.totalSideCount[0]>s.totalSideCount[1]){this.multiplyNormals(normals,opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB);line.shorten(opts.bondLength-opts.shortBondLength*opts.bondLength),svgWrapper.drawLine(line),svgWrapper.drawLine(new Line(a,b,elementA,elementB))}else if(s.sideCount[0]_Mathabs2(_MathPI3-angle)&&svgWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,vertex.value.chirality)}if(opts.debug)for(var i=0;i {\r\n const context = canvas.getContext('2d');\r\n context.clearRect(0, 0, canvas.width, canvas.height);\r\n })\r\n};\r\n\r\n/**\r\n* Parses the entered smiles string.\r\n*\r\n* @static\r\n* @param {String} smiles A SMILES string.\r\n* @param {Function} successCallback A callback that is called on success with the parse tree.\r\n* @param {Function} errorCallback A callback that is called with the error object on error.\r\n*/\r\nSmilesDrawer.parse = function(smiles, successCallback, errorCallback) {\r\n try {\r\n if (successCallback) {\r\n successCallback(Parser.parse(smiles));\r\n }\r\n } catch (err) {\r\n if (errorCallback) {\r\n errorCallback(err);\r\n }\r\n }\r\n};\r\n\r\nif (canUseDOM) {\r\n window.SmilesDrawer = SmilesDrawer;\r\n}\r\n\r\n// There be dragons (polyfills)\r\n\r\nif (!Array.prototype.fill) {\r\nObject.defineProperty(Array.prototype, 'fill', {\r\n value: function(value) {\r\n\r\n // Steps 1-2.\r\n if (this == null) {\r\n throw new TypeError('this is null or not defined');\r\n }\r\n\r\n var O = Object(this);\r\n\r\n // Steps 3-5.\r\n var len = O.length >>> 0;\r\n\r\n // Steps 6-7.\r\n var start = arguments[1];\r\n var relativeStart = start >> 0;\r\n\r\n // Step 8.\r\n var k = relativeStart < 0 ?\r\n Math.max(len + relativeStart, 0) :\r\n Math.min(relativeStart, len);\r\n\r\n // Steps 9-10.\r\n var end = arguments[2];\r\n var relativeEnd = end === undefined ?\r\n len : end >> 0;\r\n\r\n // Step 11.\r\n var final = relativeEnd < 0 ?\r\n Math.max(len + relativeEnd, 0) :\r\n Math.min(relativeEnd, len);\r\n\r\n // Step 12.\r\n while (k < final) {\r\n O[k] = value;\r\n k++;\r\n }\r\n\r\n // Step 13.\r\n return O;\r\n }\r\n});\r\n}\r\n\r\nmodule.exports = SmilesDrawer;","//@ts-check\r\n\r\n/** \r\n * A static class containing helper functions for array-related tasks. \r\n */\r\nclass ArrayHelper {\r\n /**\r\n * Clone an array or an object. If an object is passed, a shallow clone will be created.\r\n *\r\n * @static\r\n * @param {*} arr The array or object to be cloned.\r\n * @returns {*} A clone of the array or object.\r\n */\r\n static clone(arr) {\r\n let out = Array.isArray(arr) ? Array() : {};\r\n \r\n for (let key in arr) {\r\n let value = arr[key];\r\n \r\n if (typeof value.clone === 'function') {\r\n out[key] = value.clone();\r\n }\r\n else {\r\n out[key] = (typeof value === 'object') ? ArrayHelper.clone(value) : value;\r\n }\r\n }\r\n \r\n return out;\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not the two arrays contain the same elements.\r\n * Only supports 1d, non-nested arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not the two arrays contain the same elements.\r\n */\r\n static equals(arrA, arrB) {\r\n if (arrA.length !== arrB.length) {\r\n return false;\r\n }\r\n\r\n let tmpA = arrA.slice().sort();\r\n let tmpB = arrB.slice().sort();\r\n\r\n for (let i = 0; i < tmpA.length; i++) {\r\n if (tmpA[i] !== tmpB[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns a string representation of an array. If the array contains objects with an id property, the id property is printed for each of the elements.\r\n *\r\n * @static\r\n * @param {Object[]} arr An array.\r\n * @param {*} arr[].id If the array contains an object with the property 'id', the properties value is printed. Else, the array elements value is printend.\r\n * @returns {String} A string representation of the array.\r\n */\r\n static print(arr) {\r\n if (arr.length == 0) {\r\n return '';\r\n }\r\n\r\n let s = '(';\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n s += arr[i].id ? arr[i].id + ', ' : arr[i] + ', ';\r\n }\r\n\r\n s = s.substring(0, s.length - 2);\r\n\r\n return s + ')';\r\n }\r\n\r\n /**\r\n * Run a function for each element in the array. The element is supplied as an argument for the callback function\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Function} callback The callback function that is called for each element.\r\n */\r\n static each(arr, callback) {\r\n for (let i = 0; i < arr.length; i++) {\r\n callback(arr[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Return the array element from an array containing objects, where a property of the object is set to a given value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {(String|Number)} property A property contained within an object in the array.\r\n * @param {(String|Number)} value The value of the property.\r\n * @returns {*} The array element matching the value.\r\n */\r\n static get(arr, property, value) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][property] == value) {\r\n return arr[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains a given value. the options object passed as a second argument can contain three properties. value: The value to be searched for. property: The property that is to be searched for a given value. func: A function that is used as a callback to return either true or false in order to do a custom comparison.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Object} options See method description.\r\n * @param {*} options.value The value for which to check.\r\n * @param {String} [options.property=undefined] The property on which to check.\r\n * @param {Function} [options.func=undefined] A custom property function.\r\n * @returns {Boolean} A boolean whether or not the array contains a value.\r\n */\r\n static contains(arr, options) {\r\n if (!options.property && !options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] == options.value) {\r\n return true;\r\n }\r\n }\r\n } else if (options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (options.func(arr[i])) {\r\n return true;\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][options.property] == options.value) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array containing the intersection between two arrays. That is, values that are common to both arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The intersecting vlaues.\r\n */\r\n static intersection(arrA, arrB) {\r\n let intersection = [];\r\n \r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n intersection.push(arrA[i]);\r\n }\r\n }\r\n }\r\n\r\n return intersection;\r\n }\r\n\r\n /**\r\n * Returns an array of unique elements contained in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @returns {Array} An array of unique elements contained within the array supplied as an argument.\r\n */\r\n static unique(arr) {\r\n let contains = {};\r\n return arr.filter(function (i) {\r\n // using !== instead of hasOwnProperty (http://andrew.hedges.name/experiments/in/)\r\n return contains[i] !== undefined ? false : (contains[i] = true);\r\n });\r\n }\r\n\r\n /**\r\n * Count the number of occurences of a value in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be counted.\r\n * @returns {Number} The number of occurences of a value in the array.\r\n */\r\n static count(arr, value) {\r\n let count = 0;\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] === value) {\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Toggles the value of an array. If a value is not contained in an array, the array returned will contain all the values of the original array including the value. If a value is contained in an array, the array returned will contain all the values of the original array excluding the value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be toggled.\r\n * @returns {Array} The toggled array.\r\n */\r\n static toggle(arr, value) {\r\n let newArr = Array();\r\n\r\n let removed = false;\r\n for (let i = 0; i < arr.length; i++) {\r\n // Do not copy value if it exists\r\n if (arr[i] !== value) {\r\n newArr.push(arr[i]);\r\n } else {\r\n // The element was not copied to the new array, which\r\n // means it was removed\r\n removed = true;\r\n }\r\n }\r\n\r\n // If the element was not removed, then it was not in the array\r\n // so add it\r\n if (!removed) {\r\n newArr.push(value);\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n /**\r\n * Remove a value from an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} A new array with the element with a given value removed.\r\n */\r\n static remove(arr, value) {\r\n let tmp = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] !== value) {\r\n tmp.push(arr[i]);\r\n }\r\n }\r\n\r\n return tmp;\r\n }\r\n\r\n /**\r\n * Remove a value from an array with unique values.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} An array with the element with a given value removed.\r\n */\r\n static removeUnique(arr, value) {\r\n let index = arr.indexOf(value);\r\n\r\n if (index > -1) {\r\n arr.splice(index, 1);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Remove all elements contained in one array from another array.\r\n *\r\n * @static\r\n * @param {Array} arrA The array to be filtered.\r\n * @param {Array} arrB The array containing elements that will be removed from the other array.\r\n * @returns {Array} The filtered array.\r\n */\r\n static removeAll(arrA, arrB) {\r\n return arrA.filter(function (item) {\r\n return arrB.indexOf(item) === -1;\r\n });\r\n }\r\n\r\n /**\r\n * Merges two arrays and returns the result. The first array will be appended to the second array.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The merged array.\r\n */\r\n static merge(arrA, arrB) {\r\n let arr = new Array(arrA.length + arrB.length);\r\n\r\n for (let i = 0; i < arrA.length; i++) {\r\n arr[i] = arrA[i];\r\n }\r\n\r\n for (let i = 0; i < arrB.length; i++) {\r\n arr[arrA.length + i] = arrB[i];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains all the elements of another array, without regard to the order.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not both array contain the same elements.\r\n */\r\n static containsAll(arrA, arrB) {\r\n let containing = 0;\r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n containing++;\r\n }\r\n }\r\n }\r\n\r\n return containing === arrB.length;\r\n }\r\n \r\n /**\r\n * Sort an array of atomic number information. Where the number is indicated as x, x.y, x.y.z, ...\r\n *\r\n * @param {Object[]} arr An array of vertex ids with their associated atomic numbers.\r\n * @param {Number} arr[].vertexId A vertex id.\r\n * @param {String} arr[].atomicNumber The atomic number associated with the vertex id.\r\n * @returns {Object[]} The array sorted by atomic number. Example of an array entry: { atomicNumber: 2, vertexId: 5 }.\r\n */\r\n static sortByAtomicNumberDesc(arr) {\r\n let map = arr.map(function(e, i) {\r\n return { index: i, value: e.atomicNumber.split('.').map(Number) };\r\n });\r\n\r\n map.sort(function(a, b) {\r\n let min = Math.min(b.value.length, a.value.length);\r\n let i = 0;\r\n \r\n while(i < min && b.value[i] === a.value[i]) {\r\n i++;\r\n }\r\n\r\n return i === min ? b.value.length - a.value.length : b.value[i] - a.value[i];\r\n });\r\n\r\n return map.map(function(e) {\r\n return arr[e.index];\r\n });\r\n }\r\n\r\n /**\r\n * Copies a an n-dimensional array.\r\n * \r\n * @param {Array} arr The array to be copied.\r\n * @returns {Array} The copy.\r\n */\r\n static deepCopy(arr) {\r\n let newArr = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n let item = arr[i];\r\n\r\n if (item instanceof Array) {\r\n newArr[i] = ArrayHelper.deepCopy(item);\r\n } else {\r\n newArr[i] = item;\r\n }\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = ArrayHelper;","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper');\r\n\r\n/** \r\n * A class representing an atom.\r\n * \r\n * @property {String} element The element symbol of this atom. Single-letter symbols are always uppercase. Examples: H, C, F, Br, Si, ...\r\n * @property {Boolean} drawExplicit A boolean indicating whether or not this atom is drawn explicitly (for example, a carbon atom). This overrides the default behaviour.\r\n * @property {Object[]} ringbonds An array containing the ringbond ids and bond types as specified in the original SMILE.\r\n * @property {String} branchBond The branch bond as defined in the SMILES.\r\n * @property {Number} ringbonds[].id The ringbond id as defined in the SMILES.\r\n * @property {String} ringbonds[].bondType The bond type of the ringbond as defined in the SMILES.\r\n * @property {Number[]} rings The ids of rings which contain this atom.\r\n * @property {String} bondType The bond type associated with this array. Examples: -, =, #, ...\r\n * @property {Boolean} isBridge A boolean indicating whether or not this atom is part of a bridge in a bridged ring (contained by the largest ring).\r\n * @property {Boolean} isBridgeNode A boolean indicating whether or not this atom is a bridge node (a member of the largest ring in a bridged ring which is connected to a bridge-atom).\r\n * @property {Number[]} originalRings Used to back up rings when they are replaced by a bridged ring.\r\n * @property {Number} bridgedRing The id of the bridged ring if the atom is part of a bridged ring.\r\n * @property {Number[]} anchoredRings The ids of the rings that are anchored to this atom. The centers of anchored rings are translated when this atom is translated.\r\n * @property {Object} bracket If this atom is defined as a bracket atom in the original SMILES, this object contains all the bracket information. Example: { hcount: {Number}, charge: ['--', '-', '+', '++'], isotope: {Number} }.\r\n * @property {Number} plane Specifies on which \"plane\" the atoms is in stereochemical deptictions (-1 back, 0 middle, 1 front).\r\n * @property {Object[]} attachedPseudoElements A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @property {String} attachedPseudoElement[].element The element symbol.\r\n * @property {Number} attachedPseudoElement[].count The number of occurences that match the key.\r\n * @property {Number} attachedPseudoElement[].hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n * @property {Boolean} hasAttachedPseudoElements A boolean indicating whether or not this attom will be drawn with an attached pseudo element or concatinated elements.\r\n * @property {Boolean} isDrawn A boolean indicating whether or not this atom is drawn. In contrast to drawExplicit, the bond is drawn neither.\r\n * @property {Boolean} isConnectedToRing A boolean indicating whether or not this atom is directly connected (but not a member of) a ring.\r\n * @property {String[]} neighbouringElements An array containing the element symbols of neighbouring atoms.\r\n * @property {Boolean} isPartOfAromaticRing A boolean indicating whether or not this atom is part of an explicitly defined aromatic ring. Example: c1ccccc1.\r\n * @property {Number} bondCount The number of bonds in which this atom is participating.\r\n * @property {String} chirality The chirality of this atom if it is a stereocenter (R or S).\r\n * @property {Number} priority The priority of this atom acording to the CIP rules, where 0 is the highest priority.\r\n * @property {Boolean} mainChain A boolean indicating whether or not this atom is part of the main chain (used for chirality).\r\n * @property {String} hydrogenDirection The direction of the hydrogen, either up or down. Only for stereocenters with and explicit hydrogen.\r\n * @property {Number} subtreeDepth The depth of the subtree coming from a stereocenter.\r\n */\r\nclass Atom {\r\n /**\r\n * The constructor of the class Atom.\r\n *\r\n * @param {String} element The one-letter code of the element.\r\n * @param {String} [bondType='-'] The type of the bond associated with this atom.\r\n */\r\n constructor(element, bondType = '-') {\r\n this.element = element.length === 1 ? element.toUpperCase() : element;\r\n this.drawExplicit = false;\r\n this.ringbonds = Array();\r\n this.rings = Array();\r\n this.bondType = bondType;\r\n this.branchBond = null;\r\n this.isBridge = false;\r\n this.isBridgeNode = false;\r\n this.originalRings = Array();\r\n this.bridgedRing = null;\r\n this.anchoredRings = Array();\r\n this.bracket = null;\r\n this.plane = 0;\r\n this.attachedPseudoElements = {};\r\n this.hasAttachedPseudoElements = false;\r\n this.isDrawn = true;\r\n this.isConnectedToRing = false;\r\n this.neighbouringElements = Array();\r\n this.isPartOfAromaticRing = element !== this.element;\r\n this.bondCount = 0;\r\n this.chirality = '';\r\n this.isStereoCenter = false;\r\n this.priority = 0;\r\n this.mainChain = false;\r\n this.hydrogenDirection = 'down';\r\n this.subtreeDepth = 1;\r\n this.hasHydrogen = false;\r\n }\r\n\r\n /**\r\n * Adds a neighbouring element to this atom.\r\n * \r\n * @param {String} element A string representing an element.\r\n */\r\n addNeighbouringElement(element) {\r\n this.neighbouringElements.push(element);\r\n }\r\n\r\n /**\r\n * Attaches a pseudo element (e.g. Ac) to the atom.\r\n * @param {String} element The element identifier (e.g. Br, C, ...).\r\n * @param {String} previousElement The element that is part of the main chain (not the terminals that are converted to the pseudo element or concatinated).\r\n * @param {Number} [hydrogenCount=0] The number of hydrogens for the element.\r\n * @param {Number} [charge=0] The charge for the element.\r\n */\r\n attachPseudoElement(element, previousElement, hydrogenCount = 0, charge = 0) {\r\n if (hydrogenCount === null) {\r\n hydrogenCount = 0;\r\n }\r\n\r\n if (charge === null) {\r\n charge = 0;\r\n }\r\n\r\n let key = hydrogenCount + element + charge;\r\n\r\n if (this.attachedPseudoElements[key]) {\r\n this.attachedPseudoElements[key].count += 1;\r\n } else {\r\n this.attachedPseudoElements[key] = {\r\n element: element,\r\n count: 1,\r\n hydrogenCount: hydrogenCount,\r\n previousElement: previousElement,\r\n charge: charge\r\n };\r\n }\r\n\r\n this.hasAttachedPseudoElements = true;\r\n }\r\n\r\n /**\r\n * Returns the attached pseudo elements sorted by hydrogen count (ascending).\r\n *\r\n * @returns {Object} The sorted attached pseudo elements.\r\n */\r\n getAttachedPseudoElements() {\r\n let ordered = {};\r\n let that = this;\r\n\r\n Object.keys(this.attachedPseudoElements).sort().forEach(function (key) {\r\n ordered[key] = that.attachedPseudoElements[key];\r\n });\r\n\r\n return ordered;\r\n }\r\n\r\n /**\r\n * Returns the number of attached pseudo elements.\r\n *\r\n * @returns {Number} The number of attached pseudo elements.\r\n */\r\n getAttachedPseudoElementsCount() {\r\n return Object.keys(this.attachedPseudoElements).length;\r\n }\r\n\r\n /**\r\n * Returns whether this atom is a heteroatom (not C and not H).\r\n *\r\n * @returns {Boolean} A boolean indicating whether this atom is a heteroatom.\r\n */\r\n isHeteroAtom() {\r\n return this.element !== 'C' && this.element !== 'H';\r\n }\r\n\r\n /**\r\n * Defines this atom as the anchor for a ring. When doing repositionings of the vertices and the vertex associated with this atom is moved, the center of this ring is moved as well.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n addAnchoredRing(ringId) {\r\n if (!ArrayHelper.contains(this.anchoredRings, {\r\n value: ringId\r\n })) {\r\n this.anchoredRings.push(ringId);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of ringbonds (breaks in rings to generate the MST of the smiles) within this atom is connected to.\r\n *\r\n * @returns {Number} The number of ringbonds this atom is connected to.\r\n */\r\n getRingbondCount() {\r\n return this.ringbonds.length;\r\n }\r\n\r\n /**\r\n * Backs up the current rings.\r\n */\r\n backupRings() {\r\n this.originalRings = Array(this.rings.length);\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings[i] = this.rings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recent backed up rings.\r\n */\r\n restoreRings() {\r\n this.rings = Array(this.originalRings.length);\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings[i] = this.originalRings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not two atoms share a common ringbond id. A ringbond is a break in a ring created when generating the spanning tree of a structure.\r\n *\r\n * @param {Atom} atomA An atom.\r\n * @param {Atom} atomB An atom.\r\n * @returns {Boolean} A boolean indicating whether or not two atoms share a common ringbond.\r\n */\r\n haveCommonRingbond(atomA, atomB) {\r\n for (let i = 0; i < atomA.ringbonds.length; i++) {\r\n for (let j = 0; j < atomB.ringbonds.length; j++) {\r\n if (atomA.ringbonds[i].id == atomB.ringbonds[j].id) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not the neighbouring elements of this atom equal the supplied array.\r\n * \r\n * @param {String[]} arr An array containing all the elements that are neighbouring this atom. E.g. ['C', 'O', 'O', 'N']\r\n * @returns {Boolean} A boolean indicating whether or not the neighbours match the supplied array of elements.\r\n */\r\n neighbouringElementsEqual(arr) {\r\n if (arr.length !== this.neighbouringElements.length) {\r\n return false;\r\n }\r\n\r\n arr.sort();\r\n this.neighbouringElements.sort();\r\n\r\n for (var i = 0; i < this.neighbouringElements.length; i++) {\r\n if (arr[i] !== this.neighbouringElements[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the atomic number of this atom.\r\n * \r\n * @returns {Number} The atomic number of this atom.\r\n */\r\n getAtomicNumber() {\r\n return Atom.atomicNumbers[this.element];\r\n }\r\n\r\n /**\r\n * Get the maximum number of bonds for this atom.\r\n * \r\n * @returns {Number} The maximum number of bonds of this atom.\r\n */\r\n getMaxBonds() {\r\n return Atom.maxBonds[this.element];\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to their maximum bonds.\r\n */\r\n static get maxBonds() {\r\n return {\r\n 'H': 1,\r\n 'C': 4,\r\n 'N': 3,\r\n 'O': 2,\r\n 'P': 3,\r\n 'S': 2,\r\n 'B': 3,\r\n 'F': 1,\r\n 'I': 1,\r\n 'Cl': 1,\r\n 'Br': 1\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic number.\r\n */\r\n static get atomicNumbers() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic mass.\r\n */\r\n static get mass() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n}\r\n\r\nmodule.exports = Atom;","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Ring = require('./Ring');\r\nconst { getChargeText } = require('./UtilityFunctions');\r\n\r\n/** \r\n * A class wrapping a canvas element.\r\n * \r\n * @property {HTMLElement} canvas The HTML element for the canvas associated with this CanvasWrapper instance.\r\n * @property {CanvasRenderingContext2D} ctx The CanvasRenderingContext2D of the canvas associated with this CanvasWrapper instance.\r\n * @property {Object} colors The colors object as defined in the SmilesDrawer options.\r\n * @property {Object} opts The SmilesDrawer options.\r\n * @property {Number} drawingWidth The width of the canvas.\r\n * @property {Number} drawingHeight The height of the canvas.\r\n * @property {Number} realWidth The width of the canvas real.\r\n * @property {Number} realHeight The height of the canvas real.\r\n * @property {Number} offsetX The horizontal offset required for centering the drawing.\r\n * @property {Number} offsetY The vertical offset required for centering the drawing.\r\n * @property {Number} fontLarge The large font size in pt.\r\n * @property {Number} fontSmall The small font size in pt.\r\n */\r\nclass CanvasWrapper {\r\n /**\r\n * The constructor for the class CanvasWrapper.\r\n *\r\n * @param {(String|HTMLElement)} target The canvas id or the canvas HTMLElement.\r\n * @param {ThemeManager} themeManager Theme manager for setting proper colors.\r\n * @param {Object} options The smiles drawer options object.\r\n */\r\n constructor(target, themeManager, options) {\r\n if (typeof target === 'string' || target instanceof String) {\r\n this.canvas = document.getElementById(target);\r\n } else {\r\n this.canvas = target;\r\n }\r\n\r\n this.ctx = this.canvas.getContext('2d');\r\n this.themeManager = themeManager;\r\n this.opts = options;\r\n this.drawingWidth = 0.0;\r\n this.drawingHeight = 0.0;\r\n this.realWidth = 0.0;\r\n this.realHeight = 0.0;\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n this.fontLarge = this.opts.fontSizeLarge + 'pt Helvetica, Arial, sans-serif';\r\n this.fontSmall = this.opts.fontSizeSmall + 'pt Helvetica, Arial, sans-serif';\r\n\r\n this.updateSize(this.opts.width, this.opts.height);\r\n\r\n this.ctx.font = this.fontLarge;\r\n this.hydrogenWidth = this.ctx.measureText('H').width;\r\n this.halfHydrogenWidth = this.hydrogenWidth / 2.0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // TODO: Find out why clear was here.\r\n // this.clear();\r\n }\r\n\r\n /**\r\n * Update the width and height of the canvas\r\n * \r\n * @param {Number} width \r\n * @param {Number} height \r\n */\r\n updateSize(width, height) {\r\n this.devicePixelRatio = window.devicePixelRatio || 1;\r\n this.backingStoreRatio = this.ctx.webkitBackingStorePixelRatio || this.ctx.mozBackingStorePixelRatio ||\r\n this.ctx.msBackingStorePixelRatio || this.ctx.oBackingStorePixelRatio ||\r\n this.ctx.backingStorePixelRatio || 1;\r\n this.ratio = this.devicePixelRatio / this.backingStoreRatio;\r\n\r\n this.canvas.width = width * this.ratio;\r\n this.canvas.height = height * this.ratio;\r\n if (this.ratio !== 1) {\r\n this.realWidth = width;\r\n this.realHeight = height;\r\n this.canvas.style.width = width + 'px';\r\n this.canvas.style.height = height + 'px';\r\n this.ctx.setTransform(this.ratio, 0, 0, this.ratio, 0, 0);\r\n }\r\n }\r\n\r\n /**\r\n * Sets a provided theme.\r\n *\r\n * @param {Object} theme A theme from the smiles drawer options.\r\n */\r\n setTheme(theme) {\r\n this.colors = theme;\r\n }\r\n\r\n /**\r\n * Scale the canvas based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n scale(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n var padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n var scaleX = this.canvas.offsetWidth / this.drawingWidth;\r\n var scaleY = this.canvas.offsetHeight / this.drawingHeight;\r\n\r\n var scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n\r\n this.ctx.scale(scale, scale);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.canvas.offsetHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.canvas.offsetWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Resets the transform of the canvas.\r\n */\r\n reset() {\r\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.colors) {\r\n return this.colors[key];\r\n }\r\n\r\n return this.colors['C'];\r\n }\r\n\r\n /**\r\n * Draws a circle to a canvas context.\r\n * @param {Number} x The x coordinate of the circles center.\r\n * @param {Number} y The y coordinate of the circles center.\r\n * @param {Number} radius The radius of the circle\r\n * @param {String} color A hex encoded color.\r\n * @param {Boolean} [fill=true] Whether to fill or stroke the circle.\r\n * @param {Boolean} [debug=false] Draw in debug mode.\r\n * @param {String} [debugText=''] A debug message.\r\n */\r\n drawCircle(x, y, radius, color, fill = true, debug = false, debugText = '') {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.lineWidth = 1.5;\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, radius, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n\r\n if (debug) {\r\n if (fill) {\r\n ctx.fillStyle = '#f00';\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = '#f00';\r\n ctx.stroke();\r\n }\r\n\r\n this.drawDebugText(x, y, debugText);\r\n } else {\r\n if (fill) {\r\n ctx.fillStyle = color;\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = color;\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a line to a canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} [dashed=false] Whether or not the line is dashed.\r\n * @param {Number} [alpha=1.0] The alpha value of the color.\r\n */\r\n drawLine(line, dashed = false, alpha = 1.0) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(4.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n // Draw the \"shadow\"\r\n if (!dashed) {\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness + 1.2;\r\n ctx.strokeStyle = this.themeManager.getColor('BACKGROUND');\r\n ctx.stroke();\r\n ctx.globalCompositeOperation = 'source-over';\r\n ctx.restore();\r\n }\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n\r\n let gradient = this.ctx.createLinearGradient(l.x, l.y, r.x, r.y);\r\n if (line.isDecayPoint) {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(\"DECAY\"));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(\"DECAY\"));\r\n } else {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n }\r\n\r\n if (dashed) {\r\n ctx.setLineDash([1, 1.5]);\r\n ctx.lineWidth = this.opts.bondThickness / 1.5;\r\n }\r\n\r\n if (alpha < 1.0) {\r\n ctx.globalAlpha = alpha;\r\n }\r\n\r\n ctx.strokeStyle = gradient;\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Number} width The wedge width.\r\n */\r\n drawWedge(line, width = 1.0) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(5.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l;\r\n let end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness));\r\n let u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness));\r\n let v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness));\r\n let w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(t.x, t.y);\r\n ctx.lineTo(u.x, u.y);\r\n ctx.lineTo(v.x, v.y);\r\n ctx.lineTo(w.x, w.y);\r\n\r\n let gradient = this.ctx.createRadialGradient(r.x, r.y, this.opts.bondLength, r.x, r.y, 0);\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n let l = line.getLeftVector().clone();\r\n let r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start;\r\n let end;\r\n let sStart;\r\n let sEnd;\r\n\r\n let shortLine = line.clone();\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n\r\n shortLine.shortenRight(1.0);\r\n\r\n sStart = shortLine.getRightVector().clone();\r\n sEnd = shortLine.getLeftVector().clone();\r\n } else {\r\n start = l;\r\n end = r;\r\n\r\n shortLine.shortenLeft(1.0);\r\n\r\n sStart = shortLine.getLeftVector().clone();\r\n sEnd = shortLine.getRightVector().clone();\r\n }\r\n\r\n sStart.x += offsetX;\r\n sStart.y += offsetY;\r\n sEnd.x += offsetX;\r\n sEnd.y += offsetY;\r\n\r\n let dir = Vector2.subtract(end, start).normalize();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n let length = line.getLength();\r\n let step = 1.25 / (length / (this.opts.bondThickness * 3.0));\r\n\r\n let changed = false;\r\n for (var t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length);\r\n let startDash = Vector2.add(start, to);\r\n let width = 1.5 * t;\r\n let dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n if (!changed && t > 0.5) {\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.strokeStyle = this.themeManager.getColor(line.getRightElement()) || this.themeManager.getColor('C');\r\n changed = true;\r\n }\r\n \r\n startDash.subtract(dashOffset);\r\n ctx.moveTo(startDash.x, startDash.y);\r\n startDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n ctx.lineTo(startDash.x, startDash.y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.font = '5px Droid Sans, sans-serif';\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'top';\r\n ctx.fillStyle = '#ff0000';\r\n ctx.fillText(text, x + this.offsetX, y + this.offsetY);\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a ball to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, this.opts.bondLength / 4.5, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a point to the canvas.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, 1.5, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, 0.75, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'alphabetic';\r\n\r\n // Charge\r\n let chargeText = '';\r\n let chargeWidth = 0;\r\n\r\n if (charge) {\r\n chargeText = getChargeText(charge);\r\n\r\n ctx.font = this.fontSmall;\r\n chargeWidth = ctx.measureText(chargeText).width;\r\n }\r\n\r\n let isotopeText = '0';\r\n let isotopeWidth = 0;\r\n\r\n if (isotope > 0) {\r\n isotopeText = isotope.toString();\r\n ctx.font = this.fontSmall;\r\n isotopeWidth = ctx.measureText(isotopeText).width;\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') && \r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = { '0O': { element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: '' } };\r\n charge = 0;\r\n }\r\n\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillStyle = this.themeManager.getColor('BACKGROUND');\r\n\r\n let dim = ctx.measureText(elementName);\r\n\r\n dim.totalWidth = dim.width + chargeWidth;\r\n dim.height = parseInt(this.fontLarge, 10);\r\n\r\n let r = (dim.width > this.opts.fontSizeLarge) ? dim.width : this.opts.fontSizeLarge;\r\n r /= 1.5;\r\n\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, r, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n let cursorPos = -dim.width / 2.0;\r\n let cursorPosLeft = -dim.width / 2.0;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fillText(elementName, x + offsetX + cursorPos, y + this.opts.halfFontSizeLarge + offsetY);\r\n cursorPos += dim.width;\r\n\r\n if (charge) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(chargeText, x + offsetX + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += chargeWidth;\r\n }\r\n\r\n if (isotope > 0) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(isotopeText, x + offsetX + cursorPosLeft - isotopeWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPosLeft -= isotopeWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hydrogenWidth = 0;\r\n let hydrogenCountWidth = 0;\r\n\r\n if (hydrogens === 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n cursorPosLeft -= hydrogenWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.fillText('H', hx, hy);\r\n\r\n cursorPos += hydrogenWidth;\r\n } else if (hydrogens > 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n ctx.font = this.fontSmall;\r\n hydrogenCountWidth = ctx.measureText(hydrogens).width;\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillText('H', hx, hy);\r\n\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogens, hx + this.halfHydrogenWidth + hydrogenCountWidth, hy + this.opts.fifthFontSizeSmall);\r\n\r\n cursorPos += hydrogenWidth + this.halfHydrogenWidth + hydrogenCountWidth;\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let openParenthesisWidth = 0;\r\n let closeParenthesisWidth = 0;\r\n\r\n let element = attachedPseudoElement[key].element;\r\n let elementCount = attachedPseudoElement[key].count;\r\n let hydrogenCount = attachedPseudoElement[key].hydrogenCount;\r\n let elementCharge = attachedPseudoElement[key].charge;\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n openParenthesisWidth = ctx.measureText('(').width;\r\n closeParenthesisWidth = ctx.measureText(')').width;\r\n }\r\n\r\n let elementWidth = ctx.measureText(element).width;\r\n let elementCountWidth = 0;\r\n\r\n let elementChargeText = '';\r\n let elementChargeWidth = 0;\r\n\r\n hydrogenWidth = 0;\r\n\r\n if (hydrogenCount > 0) {\r\n hydrogenWidth = this.hydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n elementCountWidth = ctx.measureText(elementCount).width;\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n elementChargeText = getChargeText(elementCharge);\r\n elementChargeWidth = ctx.measureText(elementChargeText).width;\r\n }\r\n\r\n hydrogenCountWidth = 0;\r\n\r\n if (hydrogenCount > 1) {\r\n hydrogenCountWidth = ctx.measureText(hydrogenCount).width;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(element);\r\n\r\n if (elementCount > 0) {\r\n cursorPosLeft -= elementCountWidth;\r\n }\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= closeParenthesisWidth;\r\n ctx.fillText(')', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText('(', hx + cursorPos, hy);\r\n cursorPos += openParenthesisWidth;\r\n }\r\n }\r\n\r\n if (direction === 'left') {\r\n cursorPosLeft -= elementWidth;\r\n ctx.fillText(element, hx + cursorPosLeft, hy)\r\n } else {\r\n ctx.fillText(element, hx + cursorPos, hy);\r\n cursorPos += elementWidth;\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n ctx.fillText('H', hx + cursorPosLeft, hy);\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPosLeft + hydrogenWidth, hy + this.opts.fifthFontSizeSmall);\r\n }\r\n } else {\r\n ctx.fillText('H', hx + cursorPos, hy);\r\n cursorPos += hydrogenWidth;\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += hydrogenCountWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= openParenthesisWidth;\r\n ctx.fillText('(', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText(')', hx + cursorPos, hy);\r\n cursorPos += closeParenthesisWidth;\r\n }\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementCount, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, hy + this.opts.fifthFontSizeSmall);\r\n } else {\r\n ctx.fillText(elementCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += elementCountWidth;\r\n }\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementChargeText, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n } else {\r\n ctx.fillText(elementChargeText, hx + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += elementChargeWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\n getChargeText(charge) {\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Draws a dubug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n this.drawCircle(x, y, 2, color, true, true, debugText);\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Clear the canvas.\r\n *\r\n */\r\n clear() {\r\n this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = CanvasWrapper;","//@ts-check\r\n\r\nclass DecayPoint {\r\n\r\n /**\r\n * Enum values for Decay points\r\n * ALL use all variants of decay points\r\n * COO -CO-O- type of decay\r\n * CONH -CO-NH- type of decay\r\n * @return {{ALL: number, COO: number, CONH: number}}\r\n */\r\n static get VALUES() {\r\n return { ALL: 0, COO: 1, CONH: 2 };\r\n }\r\n}\r\n\r\nmodule.exports = DecayPoint;\r\n","//@ts-check\r\n\r\nclass DecayState {\r\n\r\n static get VALUES() {\r\n return { NO: 0, STANDARD: 1, SOURCE: 2, STANDARD_AND_SOURCE: 3};\r\n }\r\n}\r\n\r\nmodule.exports = DecayState;\r\n","\r\nclass Direction {\r\n\r\n static get VALUES() {\r\n return { N: 0, POLYKETIDE: 1, C: 2 };\r\n }\r\n\r\n static getProperValue(isPolyketide, vertexElement, vertexId, firstVertexId) {\r\n if (isPolyketide) {\r\n return this.VALUES.POLYKETIDE;\r\n }\r\n if (vertexElement === \"C\" && vertexId !== firstVertexId) {\r\n return this.VALUES.C;\r\n }\r\n return this.VALUES.N;\r\n }\r\n\r\n}\r\n\r\nmodule.exports= Direction;\r\n","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Atom = require('./Atom');\r\nconst Ring = require('./Ring');\r\nconst RingConnection = require('./RingConnection');\r\nconst CanvasWrapper = require('./CanvasWrapper');\r\nconst Graph = require('./Graph');\r\nconst SSSR = require('./SSSR');\r\nconst DecayState = require('./DecayState');\r\nconst ThemeManager = require('./ThemeManager');\r\n\r\n/**\r\n * The main class of the application representing the smiles drawer\r\n *\r\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\r\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\r\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} totalOverlapScore The current internal total overlap score.\r\n * @property {Object} defaultOptions The default options.\r\n * @property {Object} opts The merged options.\r\n * @property {Object} theme The current theme.\r\n */\r\nclass Drawer {\r\n /**\r\n * The constructor for the class SmilesDrawer.\r\n *\r\n * @param {Object} options An object containing custom values for different options. It is merged with the default options.\r\n */\r\n constructor(options) {\r\n this.graph = null;\r\n this.doubleBondConfigCount = 0;\r\n this.doubleBondConfig = null;\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n this.canvasWrapper = null;\r\n this.totalOverlapScore = 0;\r\n\r\n this.defaultOptions = {\r\n width: 500,\r\n height: 500,\r\n offsetX: 0, /* offsetX offset of canvas in page X. Typically canvas.offsetLeft */\r\n offsetY: 0, /* offsetY offset of canvas in page Y. Typically canvas.offsetTop */\r\n bondThickness: 0.6,\r\n bondLength: 15,\r\n shortBondLength: 0.85,\r\n bondSpacing: 0.18 * 15,\r\n atomVisualization: 'default',\r\n isomeric: true,\r\n debug: false,\r\n terminalCarbons: false,\r\n explicitHydrogens: false,\r\n overlapSensitivity: 0.42,\r\n overlapResolutionIterations: 1,\r\n compactDrawing: true,\r\n fontSizeLarge: 5,\r\n fontSizeSmall: 3,\r\n padding: 20.0,\r\n experimentalSSSR: false,\r\n kkThreshold: 0.1,\r\n kkInnerThreshold: 0.1,\r\n kkMaxIteration: 20000,\r\n kkMaxInnerIteration: 50,\r\n kkMaxEnergy: 1e9,\r\n drawDecayPoints: DecayState.VALUES.NO,\r\n decaySource: [],\r\n mouseTolerance: 3,\r\n themes: {\r\n dark: {\r\n C: '#fff',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#fff',\r\n BACKGROUND: '#141414',\r\n DECAY: '#027c21'\r\n },\r\n light: {\r\n C: '#222',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#222',\r\n BACKGROUND: '#fff',\r\n DECAY: '#027c21'\r\n }\r\n }\r\n };\r\n\r\n this.opts = this.extend(true, this.defaultOptions, options);\r\n this.opts.halfBondSpacing = this.opts.bondSpacing / 2.0;\r\n this.opts.bondLengthSq = this.opts.bondLength * this.opts.bondLength;\r\n this.opts.halfFontSizeLarge = this.opts.fontSizeLarge / 2.0;\r\n this.opts.quarterFontSizeLarge = this.opts.fontSizeLarge / 4.0;\r\n this.opts.fifthFontSizeSmall = this.opts.fontSizeSmall / 5.0;\r\n\r\n // Set the default theme.\r\n this.theme = this.opts.themes.dark;\r\n\r\n this.drawDecayPoints = this.opts.drawDecayPoints;\r\n }\r\n\r\n /**\r\n * A helper method to extend the default options with user supplied ones.\r\n */\r\n extend() {\r\n let that = this;\r\n let extended = {};\r\n let deep = false;\r\n let i = 0;\r\n let length = arguments.length;\r\n\r\n if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {\r\n deep = arguments[0];\r\n i++;\r\n }\r\n\r\n let merge = function (obj) {\r\n for (var prop in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, prop)) {\r\n if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\r\n extended[prop] = that.extend(true, extended[prop], obj[prop]);\r\n } else {\r\n extended[prop] = obj[prop];\r\n }\r\n }\r\n }\r\n };\r\n\r\n for (; i < length; i++) {\r\n let obj = arguments[i];\r\n merge(obj);\r\n }\r\n\r\n return extended;\r\n }\r\n\r\n /**\r\n * Is setup to draw decay points?\r\n * when boolean this.drawDecayPoint is true then return isDecay\r\n * @param isDecay bool - edge.isDecay\r\n * @returns {Boolean}\r\n */\r\n isDrawDecayPoint(isDecay) {\r\n return this.drawDecayPoints !== DecayState.VALUES.NO && isDecay;\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to a canvas element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n this.initDraw(data, themeName, infoOnly);\r\n\r\n if (!this.infoOnly) {\r\n this.themeManager = new ThemeManager(this.opts.themes, themeName);\r\n this.canvasWrapper = new CanvasWrapper(target, this.themeManager, this.opts);\r\n }\r\n\r\n if (!infoOnly) {\r\n this.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n\r\n if (this.opts.debug) {\r\n console.log(this.graph);\r\n console.log(this.rings);\r\n console.log(this.ringConnections);\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n if (this.canvasWrapper) {\r\n this.canvasWrapper.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of rings this edge is a part of.\r\n *\r\n * @param {Number} edgeId The id of an edge.\r\n * @returns {Number} The number of rings the provided edge is part of.\r\n */\r\n edgeRingCount(edgeId) {\r\n let edge = this.graph.edges[edgeId];\r\n let a = this.graph.vertices[edge.sourceId];\r\n let b = this.graph.vertices[edge.targetId];\r\n\r\n return Math.min(a.value.rings.length, b.value.rings.length);\r\n }\r\n\r\n /**\r\n * Returns an array containing the bridged rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all bridged rings associated with this molecule.\r\n */\r\n getBridgedRings() {\r\n let bridgedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n bridgedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return bridgedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all fused rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all fused rings associated with this molecule.\r\n */\r\n getFusedRings() {\r\n let fusedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isFused) {\r\n fusedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return fusedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all spiros associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all spiros associated with this molecule.\r\n */\r\n getSpiros() {\r\n let spiros = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isSpiro) {\r\n spiros.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return spiros;\r\n }\r\n\r\n /**\r\n * Returns a string containing a semicolon and new-line separated list of ring properties: Id; Members Count; Neighbours Count; IsSpiro; IsFused; IsBridged; Ring Count (subrings of bridged rings)\r\n *\r\n * @returns {String} A string as described in the method description.\r\n */\r\n printRingInfo() {\r\n let result = '';\r\n for (let i = 0; i < this.rings.length; i++) {\r\n const ring = this.rings[i];\r\n\r\n result += ring.id + ';';\r\n result += ring.members.length + ';';\r\n result += ring.neighbours.length + ';';\r\n result += ring.isSpiro ? 'true;' : 'false;';\r\n result += ring.isFused ? 'true;' : 'false;';\r\n result += ring.isBridged ? 'true;' : 'false;';\r\n result += ring.rings.length + ';';\r\n result += '\\n';\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Rotates the drawing to make the widest dimension horizontal.\r\n */\r\n rotateDrawing() {\r\n // Rotate the vertices to make the molecule align horizontally\r\n // Find the longest distance\r\n let a = 0;\r\n let b = 0;\r\n let maxDist = 0;\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertexA = this.graph.vertices[i];\r\n\r\n if (!vertexA.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n for (let j = i + 1; j < this.graph.vertices.length; j++) {\r\n let vertexB = this.graph.vertices[j];\r\n\r\n if (!vertexB.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = vertexA.position.distanceSq(vertexB.position);\r\n\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n a = i;\r\n b = j;\r\n }\r\n }\r\n }\r\n\r\n let angle = -Vector2.subtract(this.graph.vertices[a].position, this.graph.vertices[b].position).angle();\r\n\r\n if (!isNaN(angle)) {\r\n // Round to 30 degrees\r\n let remainder = angle % 0.523599;\r\n\r\n // Round either up or down in 30 degree steps\r\n if (remainder < 0.2617995) {\r\n angle = angle - remainder;\r\n } else {\r\n angle += 0.523599 - remainder;\r\n }\r\n\r\n // Finally, rotate everything\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (i === b) {\r\n continue;\r\n }\r\n\r\n this.graph.vertices[i].position.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.rings[i].center.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.totalOverlapScore;\r\n }\r\n\r\n /**\r\n * Returns the ring count of the current molecule.\r\n *\r\n * @returns {Number} The ring count.\r\n */\r\n getRingCount() {\r\n return this.rings.length;\r\n }\r\n\r\n /**\r\n * Checks whether or not the current molecule a bridged ring.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not the current molecule a bridged ring.\r\n */\r\n hasBridgedRing() {\r\n return this.bridgedRing;\r\n }\r\n\r\n /**\r\n * Returns the number of heavy atoms (non-hydrogen) in the current molecule.\r\n *\r\n * @returns {Number} The heavy atom count.\r\n */\r\n getHeavyAtomCount() {\r\n let hac = 0;\r\n\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.element !== 'H') {\r\n hac++;\r\n }\r\n }\r\n\r\n return hac;\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n let molecularFormula = '';\r\n let counts = new Map();\r\n\r\n // Initialize element count\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n let atom = this.graph.vertices[i].value;\r\n\r\n if (counts.has(atom.element)) {\r\n counts.set(atom.element, counts.get(atom.element) + 1);\r\n } else {\r\n counts.set(atom.element, 1);\r\n }\r\n\r\n // Hydrogens attached to a chiral center were added as vertices,\r\n // those in non chiral brackets are added here\r\n if (atom.bracket && !atom.bracket.chirality) {\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + atom.bracket.hcount);\r\n } else {\r\n counts.set('H', atom.bracket.hcount);\r\n }\r\n }\r\n\r\n // Add the implicit hydrogens according to valency, exclude\r\n // bracket atoms as they were handled and always have the number\r\n // of hydrogens specified explicitly\r\n if (!atom.bracket) {\r\n let nHydrogens = Atom.maxBonds[atom.element] - atom.bondCount;\r\n\r\n if (atom.isPartOfAromaticRing) {\r\n nHydrogens--;\r\n }\r\n\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + nHydrogens);\r\n } else {\r\n counts.set('H', nHydrogens);\r\n }\r\n }\r\n }\r\n\r\n if (counts.has('C')) {\r\n let count = counts.get('C');\r\n molecularFormula += 'C' + (count > 1 ? count : '');\r\n counts.delete('C');\r\n }\r\n\r\n if (counts.has('H')) {\r\n let count = counts.get('H');\r\n molecularFormula += 'H' + (count > 1 ? count : '');\r\n counts.delete('H');\r\n }\r\n\r\n let elements = Object.keys(Atom.atomicNumbers).sort();\r\n\r\n elements.map(e => {\r\n if (counts.has(e)) {\r\n let count = counts.get(e);\r\n molecularFormula += e + (count > 1 ? count : '');\r\n }\r\n });\r\n\r\n return molecularFormula;\r\n }\r\n\r\n /**\r\n * Returns the type of the ringbond (e.g. '=' for a double bond). The ringbond represents the break in a ring introduced when creating the MST. If the two vertices supplied as arguments are not part of a common ringbond, the method returns null.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(String|null)} Returns the ringbond type or null, if the two supplied vertices are not connected by a ringbond.\r\n */\r\n getRingbondType(vertexA, vertexB) {\r\n // Checks whether the two vertices are the ones connecting the ring\r\n // and what the bond type should be.\r\n if (vertexA.value.getRingbondCount() < 1 || vertexB.value.getRingbondCount() < 1) {\r\n return null;\r\n }\r\n\r\n for (var i = 0; i < vertexA.value.ringbonds.length; i++) {\r\n for (var j = 0; j < vertexB.value.ringbonds.length; j++) {\r\n // if(i != j) continue;\r\n if (vertexA.value.ringbonds[i].id === vertexB.value.ringbonds[j].id) {\r\n // If the bonds are equal, it doesn't matter which bond is returned.\r\n // if they are not equal, return the one that is not the default (\"-\")\r\n if (vertexA.value.ringbonds[i].bondType === '-') {\r\n return vertexB.value.ringbonds[j].bond;\r\n } else {\r\n return vertexA.value.ringbonds[i].bond;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n initDraw(data, themeName, infoOnly) {\r\n this.data = data;\r\n this.infoOnly = infoOnly;\r\n\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n\r\n this.graph = new Graph(data, this.opts.isomeric, this.opts);\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n this.bridgedRing = false;\r\n\r\n // Reset those, in case the previous drawn SMILES had a dangling \\ or /\r\n this.doubleBondConfigCount = null;\r\n this.doubleBondConfig = null;\r\n\r\n this.initRings();\r\n this.initHydrogens();\r\n this.graph.findDecayPoints();\r\n }\r\n\r\n processGraph() {\r\n this.position();\r\n\r\n // Restore the ring information (removes bridged rings and replaces them with the original, multiple, rings)\r\n this.restoreRingInformation();\r\n\r\n // Atoms bonded to the same ring atom\r\n this.resolvePrimaryOverlaps();\r\n\r\n let overlapScore = this.getOverlapScore();\r\n\r\n this.totalOverlapScore = this.getOverlapScore().total;\r\n\r\n for (var o = 0; o < this.opts.overlapResolutionIterations; o++) {\r\n for (var i = 0; i < this.graph.edges.length; i++) {\r\n let edge = this.graph.edges[i];\r\n if (this.isEdgeRotatable(edge)) {\r\n let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\r\n let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\r\n\r\n // Only rotate the shorter subtree\r\n let a = edge.targetId;\r\n let b = edge.sourceId;\r\n\r\n if (subTreeDepthA > subTreeDepthB) {\r\n a = edge.sourceId;\r\n b = edge.targetId;\r\n }\r\n\r\n let subTreeOverlap = this.getSubtreeOverlapScore(b, a, overlapScore.vertexScores);\r\n if (subTreeOverlap.value > this.opts.overlapSensitivity) {\r\n let vertexA = this.graph.vertices[a];\r\n let vertexB = this.graph.vertices[b];\r\n let neighboursB = vertexB.getNeighbours(a);\r\n\r\n if (neighboursB.length === 1) {\r\n let neighbour = this.graph.vertices[neighboursB[0]];\r\n let angle = neighbour.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbour.id, vertexB.id, angle, vertexB.position);\r\n // If the new overlap is bigger, undo change\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbour.id, vertexB.id, -angle, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n } else if (neighboursB.length === 2) {\r\n // Switch places / sides\r\n // If vertex a is in a ring, do nothing\r\n if (vertexB.value.rings.length !== 0 && vertexA.value.rings.length !== 0) {\r\n continue;\r\n }\r\n\r\n let neighbourA = this.graph.vertices[neighboursB[0]];\r\n let neighbourB = this.graph.vertices[neighboursB[1]];\r\n\r\n if (neighbourA.value.rings.length === 1 && neighbourB.value.rings.length === 1) {\r\n // Both neighbours in same ring. TODO: does this create problems with wedges? (up = down and vice versa?)\r\n if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\r\n continue;\r\n }\r\n // TODO: Rotate circle\r\n } else if (neighbourA.value.rings.length !== 0 || neighbourB.value.rings.length !== 0) {\r\n continue;\r\n } else {\r\n let angleA = neighbourA.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n let angleB = neighbourB.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbourA.id, vertexB.id, angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, angleB, vertexB.position);\r\n\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbourA.id, vertexB.id, -angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, -angleB, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n }\r\n }\r\n\r\n overlapScore = this.getOverlapScore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.resolveSecondaryOverlaps(overlapScore.scores);\r\n\r\n if (this.opts.isomeric) {\r\n this.annotateStereochemistry();\r\n }\r\n\r\n // Initialize pseudo elements or shortcuts\r\n if (this.opts.compactDrawing && this.opts.atomVisualization === 'default') {\r\n this.initPseudoElements();\r\n }\r\n\r\n this.rotateDrawing();\r\n }\r\n\r\n /**\r\n * Initializes rings and ringbonds for the current molecule.\r\n */\r\n initRings() {\r\n let openBonds = new Map();\r\n\r\n // Close the open ring bonds (spanning tree -> graph)\r\n for (let i = this.graph.vertices.length - 1; i >= 0; i--) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.ringbonds.length === 0) {\r\n continue;\r\n }\r\n\r\n for (let j = 0; j < vertex.value.ringbonds.length; j++) {\r\n let ringbondId = vertex.value.ringbonds[j].id;\r\n let ringbondBond = vertex.value.ringbonds[j].bond;\r\n\r\n // If the other ringbond id has not been discovered,\r\n // add it to the open bonds map and continue.\r\n // if the other ringbond id has already been discovered,\r\n // create a bond between the two atoms.\r\n if (!openBonds.has(ringbondId)) {\r\n openBonds.set(ringbondId, [vertex.id, ringbondBond]);\r\n } else {\r\n let sourceVertexId = vertex.id;\r\n let targetVertexId = openBonds.get(ringbondId)[0];\r\n let targetRingbondBond = openBonds.get(ringbondId)[1];\r\n let edge = new Edge(sourceVertexId, targetVertexId, 1);\r\n edge.setBondType(targetRingbondBond || ringbondBond || '-');\r\n let edgeId = this.graph.addEdge(edge);\r\n let targetVertex = this.graph.vertices[targetVertexId];\r\n\r\n vertex.addRingbondChild(targetVertexId, j);\r\n vertex.value.addNeighbouringElement(targetVertex.value.element);\r\n targetVertex.addRingbondChild(sourceVertexId, j);\r\n targetVertex.value.addNeighbouringElement(vertex.value.element);\r\n vertex.edges.push(edgeId);\r\n targetVertex.edges.push(edgeId);\r\n\r\n openBonds.delete(ringbondId);\r\n }\r\n }\r\n }\r\n\r\n // Get the rings in the graph (the SSSR)\r\n let rings = SSSR.getRings(this.graph, this.opts.experimentalSSSR);\r\n\r\n if (rings === null) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < rings.length; i++) {\r\n let ringVertices = [...rings[i]];\r\n let ringId = this.addRing(new Ring(ringVertices));\r\n\r\n // Add the ring to the atoms\r\n for (let j = 0; j < ringVertices.length; j++) {\r\n this.graph.vertices[ringVertices[j]].value.rings.push(ringId);\r\n }\r\n }\r\n\r\n // Find connection between rings\r\n // Check for common vertices and create ring connections. This is a bit\r\n // ugly, but the ringcount is always fairly low (< 100)\r\n for (let i = 0; i < this.rings.length - 1; i++) {\r\n for (let j = i + 1; j < this.rings.length; j++) {\r\n let a = this.rings[i];\r\n let b = this.rings[j];\r\n let ringConnection = new RingConnection(a, b);\r\n\r\n // If there are no vertices in the ring connection, then there\r\n // is no ring connection\r\n if (ringConnection.vertices.size > 0) {\r\n this.addRingConnection(ringConnection);\r\n }\r\n }\r\n }\r\n\r\n // Add neighbours to the rings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n ring.neighbours = RingConnection.getNeighbours(this.ringConnections, ring.id);\r\n }\r\n\r\n // Anchor the ring to one of it's members, so that the ring center will always\r\n // be tied to a single vertex when doing repositionings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n this.graph.vertices[ring.members[0]].value.addAnchoredRing(ring.id);\r\n }\r\n\r\n // Backup the ring information to restore after placing the bridged ring.\r\n // This is needed in order to identify aromatic rings and stuff like this in\r\n // rings that are member of the superring.\r\n this.backupRingInformation();\r\n\r\n\r\n // Replace rings contained by a larger bridged ring with a bridged ring\r\n while (this.rings.length > 0) {\r\n let id = -1;\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isPartOfBridgedRing(ring.id) && !ring.isBridged) {\r\n id = ring.id;\r\n }\r\n }\r\n\r\n if (id === -1) {\r\n break;\r\n }\r\n\r\n let ring = this.getRing(id);\r\n\r\n let involvedRings = this.getBridgedRingRings(ring.id);\r\n\r\n this.bridgedRing = true;\r\n this.createBridgedRing(involvedRings, ring.members[0]);\r\n\r\n // Remove the rings\r\n for (let i = 0; i < involvedRings.length; i++) {\r\n this.removeRing(involvedRings[i]);\r\n }\r\n }\r\n }\r\n\r\n initHydrogens() {\r\n // Do not draw hydrogens except when they are connected to a stereocenter connected to two or more rings.\r\n if (!this.opts.explicitHydrogens) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.element !== 'H') {\r\n continue;\r\n }\r\n\r\n // Hydrogens should have only one neighbour, so just take the first\r\n // Also set hasHydrogen true on connected atom\r\n let neighbour = this.graph.vertices[vertex.neighbours[0]];\r\n neighbour.value.hasHydrogen = true;\r\n\r\n if (!neighbour.value.isStereoCenter || neighbour.value.rings.length < 2 && !neighbour.value.bridgedRing ||\r\n neighbour.value.bridgedRing && neighbour.value.originalRings.length < 2) {\r\n vertex.value.isDrawn = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns all rings connected by bridged bonds starting from the ring with the supplied ring id.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array containing all ring ids of rings part of a bridged ring system.\r\n */\r\n getBridgedRingRings(ringId) {\r\n let involvedRings = Array();\r\n let that = this;\r\n\r\n let recurse = function (r) {\r\n let ring = that.getRing(r);\r\n\r\n involvedRings.push(r);\r\n\r\n for (let i = 0; i < ring.neighbours.length; i++) {\r\n let n = ring.neighbours[i];\r\n\r\n if (involvedRings.indexOf(n) === -1 &&\r\n n !== r &&\r\n RingConnection.isBridge(that.ringConnections, that.graph.vertices, r, n)) {\r\n recurse(n);\r\n }\r\n }\r\n };\r\n\r\n recurse(ringId);\r\n\r\n return ArrayHelper.unique(involvedRings);\r\n }\r\n\r\n /**\r\n * Checks whether or not a ring is part of a bridged ring.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not the supplied ring (by id) is part of a bridged ring system.\r\n */\r\n isPartOfBridgedRing(ringId) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].containsRing(ringId) &&\r\n this.ringConnections[i].isBridge(this.graph.vertices)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Creates a bridged ring.\r\n *\r\n * @param {Number[]} ringIds An array of ids of rings involved in the bridged ring.\r\n * @param {Number} sourceVertexId The vertex id to start the bridged ring discovery from.\r\n * @returns {Ring} The bridged ring.\r\n */\r\n createBridgedRing(ringIds, sourceVertexId) {\r\n let ringMembers = new Set();\r\n let vertices = new Set();\r\n let neighbours = new Set();\r\n\r\n for (let i = 0; i < ringIds.length; i++) {\r\n let ring = this.getRing(ringIds[i]);\r\n ring.isPartOfBridged = true;\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n vertices.add(ring.members[j]);\r\n }\r\n\r\n for (let j = 0; j < ring.neighbours.length; j++) {\r\n let id = ring.neighbours[j];\r\n\r\n if (ringIds.indexOf(id) === -1) {\r\n neighbours.add(ring.neighbours[j]);\r\n }\r\n }\r\n }\r\n\r\n // A vertex is part of the bridged ring if it only belongs to\r\n // one of the rings (or to another ring\r\n // which is not part of the bridged ring).\r\n let leftovers = new Set();\r\n\r\n for (let id of vertices) {\r\n let vertex = this.graph.vertices[id];\r\n let intersection = ArrayHelper.intersection(ringIds, vertex.value.rings);\r\n\r\n if (vertex.value.rings.length === 1 || intersection.length === 1) {\r\n ringMembers.add(vertex.id);\r\n } else {\r\n leftovers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Vertices can also be part of multiple rings and lay on the bridged ring,\r\n // however, they have to have at least two neighbours that are not part of\r\n // two rings\r\n let insideRing = Array();\r\n for (let id of leftovers) {\r\n let vertex = this.graph.vertices[id];\r\n let onRing = false;\r\n\r\n for (let j = 0; j < vertex.edges.length; j++) {\r\n if (this.edgeRingCount(vertex.edges[j]) === 1) {\r\n onRing = true;\r\n }\r\n }\r\n\r\n if (onRing) {\r\n vertex.value.isBridgeNode = true;\r\n ringMembers.add(vertex.id);\r\n } else {\r\n vertex.value.isBridge = true;\r\n ringMembers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Create the ring\r\n let ring = new Ring([...ringMembers]);\r\n this.addRing(ring);\r\n\r\n ring.isBridged = true;\r\n ring.neighbours = [...neighbours];\r\n for (let i = 0; i < ringIds.length; i++) {\r\n ring.rings.push(this.getRing(ringIds[i]).clone());\r\n }\r\n\r\n for (let i = 0; i < ring.members.length; i++) {\r\n this.graph.vertices[ring.members[i]].value.bridgedRing = ring.id;\r\n }\r\n\r\n // Atoms inside the ring are no longer part of a ring but are now\r\n // associated with the bridged ring\r\n for (let i = 0; i < insideRing.length; i++) {\r\n let vertex = this.graph.vertices[insideRing[i]];\r\n vertex.value.rings = Array();\r\n }\r\n\r\n // Remove former rings from members of the bridged ring and add the bridged ring\r\n for (let id of ringMembers) {\r\n let vertex = this.graph.vertices[id];\r\n vertex.value.rings = ArrayHelper.removeAll(vertex.value.rings, ringIds);\r\n vertex.value.rings.push(ring.id);\r\n }\r\n\r\n // Remove all the ring connections no longer used\r\n for (let i = 0; i < ringIds.length; i++) {\r\n for (let j = i + 1; j < ringIds.length; j++) {\r\n this.removeRingConnectionsBetween(ringIds[i], ringIds[j]);\r\n }\r\n }\r\n\r\n // Update the ring connections and add this ring to the neighbours neighbours\r\n for (let id of neighbours) {\r\n let connections = this.getRingConnections(id, ringIds);\r\n\r\n for (let j = 0; j < connections.length; j++) {\r\n this.getRingConnection(connections[j]).updateOther(ring.id, id);\r\n }\r\n\r\n this.getRing(id).neighbours.push(ring.id);\r\n }\r\n\r\n return ring;\r\n }\r\n\r\n /**\r\n * Checks whether or not two vertices are in the same ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices are in the same ring.\r\n */\r\n areVerticesInSameRing(vertexA, vertexB) {\r\n // This is a little bit lighter (without the array and push) than\r\n // getCommonRings().length > 0\r\n for (let i = 0; i < vertexA.value.rings.length; i++) {\r\n for (let j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] === vertexB.value.rings[j]) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array of ring ids shared by both vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Number[]} An array of ids of rings shared by the two vertices.\r\n */\r\n getCommonRings(vertexA, vertexB) {\r\n let commonRings = Array();\r\n\r\n for (var i = 0; i < vertexA.value.rings.length; i++) {\r\n for (var j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] == vertexB.value.rings[j]) {\r\n commonRings.push(vertexA.value.rings[i]);\r\n }\r\n }\r\n }\r\n\r\n return commonRings;\r\n }\r\n\r\n /**\r\n * Returns the aromatic or largest ring shared by the two vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(Ring|null)} If an aromatic common ring exists, that ring, else the largest (non-aromatic) ring, else null.\r\n */\r\n getLargestOrAromaticCommonRing(vertexA, vertexB) {\r\n let commonRings = this.getCommonRings(vertexA, vertexB);\r\n let maxSize = 0;\r\n let largestCommonRing = null;\r\n\r\n for (let i = 0; i < commonRings.length; i++) {\r\n let ring = this.getRing(commonRings[i]);\r\n let size = ring.getSize();\r\n\r\n if (ring.isBenzeneLike(this.graph.vertices)) {\r\n return ring;\r\n } else if (size > maxSize) {\r\n maxSize = size;\r\n largestCommonRing = ring;\r\n }\r\n }\r\n\r\n return largestCommonRing;\r\n }\r\n\r\n /**\r\n * Returns an array of vertices positioned at a specified location.\r\n *\r\n * @param {Vector2} position The position to search for vertices.\r\n * @param {Number} radius The radius within to search.\r\n * @param {Number} excludeVertexId A vertex id to be excluded from the search results.\r\n * @returns {Number[]} An array containing vertex ids in a given location.\r\n */\r\n getVerticesAt(position, radius, excludeVertexId) {\r\n let locals = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.id === excludeVertexId || !vertex.positioned) {\r\n continue;\r\n }\r\n\r\n let distance = position.distanceSq(vertex.position);\r\n\r\n if (distance <= radius * radius) {\r\n locals.push(vertex.id);\r\n }\r\n }\r\n\r\n return locals;\r\n }\r\n\r\n /**\r\n * Returns the closest vertex (connected as well as unconnected).\r\n *\r\n * @param {Vertex} vertex The vertex of which to find the closest other vertex.\r\n * @returns {Vertex} The closest vertex.\r\n */\r\n getClosestVertex(vertex) {\r\n let minDist = 99999;\r\n let minVertex = null;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i];\r\n\r\n if (v.id === vertex.id) {\r\n continue;\r\n }\r\n\r\n let distSq = vertex.position.distanceSq(v.position);\r\n\r\n if (distSq < minDist) {\r\n minDist = distSq;\r\n minVertex = v;\r\n }\r\n }\r\n\r\n return minVertex;\r\n }\r\n\r\n /**\r\n * Add a ring to this representation of a molecule.\r\n *\r\n * @param {Ring} ring A new ring.\r\n * @returns {Number} The ring id of the new ring.\r\n */\r\n addRing(ring) {\r\n ring.id = this.ringIdCounter++;\r\n this.rings.push(ring);\r\n\r\n return ring.id;\r\n }\r\n\r\n /**\r\n * Removes a ring from the array of rings associated with the current molecule.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n removeRing(ringId) {\r\n this.rings = this.rings.filter(function (item) {\r\n return item.id !== ringId;\r\n });\r\n\r\n // Also remove ring connections involving this ring\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.firstRingId !== ringId && item.secondRingId !== ringId;\r\n });\r\n\r\n // Remove the ring as neighbour of other rings\r\n for (var i = 0; i < this.rings.length; i++) {\r\n let r = this.rings[i];\r\n r.neighbours = r.neighbours.filter(function (item) {\r\n return item !== ringId;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets a ring object from the array of rings associated with the current molecule by its id. The ring id is not equal to the index, since rings can be added and removed when processing bridged rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Ring} A ring associated with the current molecule.\r\n */\r\n getRing(ringId) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].id == ringId) {\r\n return this.rings[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Add a ring connection to this representation of a molecule.\r\n *\r\n * @param {RingConnection} ringConnection A new ringConnection.\r\n * @returns {Number} The ring connection id of the new ring connection.\r\n */\r\n addRingConnection(ringConnection) {\r\n ringConnection.id = this.ringConnectionIdCounter++;\r\n this.ringConnections.push(ringConnection);\r\n\r\n return ringConnection.id;\r\n }\r\n\r\n /**\r\n * Removes a ring connection from the array of rings connections associated with the current molecule.\r\n *\r\n * @param {Number} ringConnectionId A ring connection id.\r\n */\r\n removeRingConnection(ringConnectionId) {\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.id !== ringConnectionId;\r\n });\r\n }\r\n\r\n /**\r\n * Removes all ring connections between two vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n */\r\n removeRingConnectionsBetween(vertexIdA, vertexIdB) {\r\n let toRemove = Array();\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let ringConnection = this.ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === vertexIdA && ringConnection.secondRingId === vertexIdB ||\r\n ringConnection.firstRingId === vertexIdB && ringConnection.secondRingId === vertexIdA) {\r\n toRemove.push(ringConnection.id);\r\n }\r\n }\r\n\r\n for (let i = 0; i < toRemove.length; i++) {\r\n this.removeRingConnection(toRemove[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Get a ring connection with a given id.\r\n *\r\n * @param {Number} id\r\n * @returns {RingConnection} The ring connection with the specified id.\r\n */\r\n getRingConnection(id) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].id == id) {\r\n return this.ringConnections[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the ring connections between a ring and a set of rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @param {Number[]} ringIds An array of ring ids.\r\n * @returns {Number[]} An array of ring connection ids.\r\n */\r\n getRingConnections(ringId, ringIds) {\r\n let ringConnections = Array();\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let rc = this.ringConnections[i];\r\n\r\n for (let j = 0; j < ringIds.length; j++) {\r\n let id = ringIds[j];\r\n\r\n if (rc.firstRingId === ringId && rc.secondRingId === id ||\r\n rc.firstRingId === id && rc.secondRingId === ringId) {\r\n ringConnections.push(rc.id);\r\n }\r\n }\r\n }\r\n\r\n return ringConnections;\r\n }\r\n\r\n /**\r\n * Returns the overlap score of the current molecule based on its positioned vertices. The higher the score, the more overlaps occur in the structure drawing.\r\n *\r\n * @returns {Object} Returns the total overlap score and the overlap score of each vertex sorted by score (higher to lower). Example: { total: 99, scores: [ { id: 0, score: 22 }, ... ] }\r\n */\r\n getOverlapScore() {\r\n let total = 0.0;\r\n let overlapScores = new Float32Array(this.graph.vertices.length);\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n overlapScores[i] = 0;\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let j = this.graph.vertices.length;\r\n while (--j > i) {\r\n let a = this.graph.vertices[i];\r\n let b = this.graph.vertices[j];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = Vector2.subtract(a.position, b.position).lengthSq();\r\n\r\n if (dist < this.opts.bondLengthSq) {\r\n let weighted = (this.opts.bondLength - Math.sqrt(dist)) / this.opts.bondLength;\r\n total += weighted;\r\n overlapScores[i] += weighted;\r\n overlapScores[j] += weighted;\r\n }\r\n }\r\n }\r\n\r\n let sortable = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n sortable.push({\r\n id: i,\r\n score: overlapScores[i]\r\n });\r\n }\r\n\r\n sortable.sort(function (a, b) {\r\n return b.score - a.score;\r\n });\r\n\r\n return {\r\n total: total,\r\n scores: sortable,\r\n vertexScores: overlapScores\r\n };\r\n }\r\n\r\n /**\r\n * When drawing a double bond, choose the side to place the double bond. E.g. a double bond should always been drawn inside a ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @param {Vector2[]} sides An array containing the two normals of the line spanned by the two provided vertices.\r\n * @returns {Object} Returns an object containing the following information: {\r\n totalSideCount: Counts the sides of each vertex in the molecule, is an array [ a, b ],\r\n totalPosition: Same as position, but based on entire molecule,\r\n sideCount: Counts the sides of each neighbour, is an array [ a, b ],\r\n position: which side to position the second bond, is 0 or 1, represents the index in the normal array. This is based on only the neighbours\r\n anCount: the number of neighbours of vertexA,\r\n bnCount: the number of neighbours of vertexB\r\n }\r\n */\r\n chooseSide(vertexA, vertexB, sides) {\r\n // Check which side has more vertices\r\n // Get all the vertices connected to the both ends\r\n let an = vertexA.getNeighbours(vertexB.id);\r\n let bn = vertexB.getNeighbours(vertexA.id);\r\n let anCount = an.length;\r\n let bnCount = bn.length;\r\n\r\n // All vertices connected to the edge vertexA to vertexB\r\n let tn = ArrayHelper.merge(an, bn);\r\n\r\n // Only considering the connected vertices\r\n let sideCount = [0, 0];\r\n\r\n for (let i = 0; i < tn.length; i++) {\r\n let v = this.graph.vertices[tn[i]].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n sideCount[0]++;\r\n } else {\r\n sideCount[1]++;\r\n }\r\n }\r\n\r\n // Considering all vertices in the graph, this is to resolve ties\r\n // from the above side counts\r\n let totalSideCount = [0, 0];\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n totalSideCount[0]++;\r\n } else {\r\n totalSideCount[1]++;\r\n }\r\n }\r\n\r\n return {\r\n totalSideCount: totalSideCount,\r\n totalPosition: totalSideCount[0] > totalSideCount[1] ? 0 : 1,\r\n sideCount: sideCount,\r\n position: sideCount[0] > sideCount[1] ? 0 : 1,\r\n anCount: anCount,\r\n bnCount: bnCount\r\n };\r\n }\r\n\r\n /**\r\n * Sets the center for a ring.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n setRingCenter(ring) {\r\n let ringSize = ring.getSize();\r\n let total = new Vector2(0, 0);\r\n\r\n for (let i = 0; i < ringSize; i++) {\r\n total.add(this.graph.vertices[ring.members[i]].position);\r\n }\r\n\r\n ring.center = total.divide(ringSize);\r\n }\r\n\r\n /**\r\n * Gets the center of a ring contained within a bridged ring and containing a given vertex.\r\n *\r\n * @param {Ring} ring A bridged ring.\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {Vector2} The center of the subring that containing the vertex.\r\n */\r\n getSubringCenter(ring, vertex) {\r\n let rings = vertex.value.originalRings;\r\n let center = ring.center;\r\n let smallest = Number.MAX_VALUE;\r\n\r\n // Always get the smallest ring.\r\n for (let i = 0; i < rings.length; i++) {\r\n for (let j = 0; j < ring.rings.length; j++) {\r\n if (rings[i] === ring.rings[j].id) {\r\n if (ring.rings[j].getSize() < smallest) {\r\n center = ring.rings[j].center;\r\n smallest = ring.rings[j].getSize();\r\n }\r\n }\r\n }\r\n }\r\n\r\n return center;\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let that = this;\r\n let drawn = Array(this.graph.edges.length);\r\n drawn.fill(false);\r\n\r\n this.graph.traverseBF(0, function (vertex) {\r\n let edges = that.graph.getEdges(vertex.id);\r\n for (let i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n that.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isRingAromatic(ring)) {\r\n this.canvasWrapper.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bonds to the canvas.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let that = this;\r\n let edge = this.graph.edges[edgeId];\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n let elementA = vertexA.value.element;\r\n let elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && this.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position;\r\n let b = vertexB.position;\r\n let normals = this.getEdgeNormals(edge);\r\n\r\n // Create a point on each side of the line\r\n let sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || this.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && this.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = this.areVerticesInSameRing(vertexA, vertexB);\r\n let s = this.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = this.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n }\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n this.canvasWrapper.drawLine(line, true);\r\n } else {\r\n this.canvasWrapper.drawLine(line);\r\n }\r\n\r\n // The normal edge\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.center || vertexA.isTerminal() && vertexB.isTerminal()) {\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1) {\r\n // Both lines are the same length here\r\n // Add the spacing to the edges (which are of unit length)\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.sideCount[0] > s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.sideCount[0] < s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] > s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] <= s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n this.canvasWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.wedge === 'down') {\r\n this.canvasWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else {\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n this.canvasWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(this.graph.vertices);\r\n let isTerminal = this.opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (this.opts.atomVisualization === 'allballs') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || this.graph.vertices.length === 1) {\r\n if (this.opts.atomVisualization === 'default') {\r\n this.canvasWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (this.opts.atomVisualization === 'balls') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = this.graph.vertices[vertex.neighbours[0]].position;\r\n let b = this.graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n this.canvasWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n // this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (this.opts.debug) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let center = this.rings[i].center;\r\n this.canvasWrapper.drawDebugPoint(center.x, center.y, 'r: ' + this.rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Position the vertices according to their bonds and properties.\r\n */\r\n position() {\r\n let startVertex = null;\r\n\r\n // Always start drawing at a bridged ring if there is one\r\n // If not, start with a ring\r\n // else, start with 0\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.bridgedRing !== null) {\r\n startVertex = this.graph.vertices[i];\r\n break;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n startVertex = this.graph.vertices[this.rings[i].members[0]];\r\n }\r\n }\r\n\r\n if (this.rings.length > 0 && startVertex === null) {\r\n startVertex = this.graph.vertices[this.rings[0].members[0]];\r\n }\r\n\r\n if (startVertex === null) {\r\n startVertex = this.graph.vertices[0];\r\n }\r\n\r\n this.createNextBond(startVertex, null, 0.0);\r\n }\r\n\r\n /**\r\n * Stores the current information associated with rings.\r\n */\r\n backupRingInformation() {\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings.push(this.rings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n this.originalRingConnections.push(this.ringConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.backupRings();\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recently backed up information associated with rings.\r\n */\r\n restoreRingInformation() {\r\n // Get the subring centers from the bridged rings\r\n let bridgedRings = this.getBridgedRings();\r\n\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n for (let i = 0; i < bridgedRings.length; i++) {\r\n let bridgedRing = bridgedRings[i];\r\n\r\n for (var j = 0; j < bridgedRing.rings.length; j++) {\r\n let ring = bridgedRing.rings[j];\r\n this.originalRings[ring.id].center = ring.center;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings.push(this.originalRings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.originalRingConnections.length; i++) {\r\n this.ringConnections.push(this.originalRingConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.restoreRings();\r\n }\r\n }\r\n\r\n // TODO: This needs some cleaning up\r\n\r\n /**\r\n * Creates a new ring, that is, positiones all the vertices inside a ring.\r\n *\r\n * @param {Ring} ring The ring to position.\r\n * @param {(Vector2|null)} [center=null] The center of the ring to be created.\r\n * @param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.\r\n * @param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.\r\n * @param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.\r\n */\r\n createRing(ring, center = null, startVertex = null, previousVertex = null) {\r\n if (ring.positioned) {\r\n return;\r\n }\r\n\r\n center = center ? center : new Vector2(0, 0);\r\n\r\n let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);\r\n let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let angle = MathHelper.centralAngle(ring.getSize());\r\n\r\n ring.centralAngle = angle;\r\n\r\n let a = startingAngle;\r\n let that = this;\r\n let startVertexId = (startVertex) ? startVertex.id : null;\r\n\r\n if (ring.members.indexOf(startVertexId) === -1) {\r\n if (startVertex) {\r\n startVertex.positioned = false;\r\n }\r\n\r\n startVertexId = ring.members[0];\r\n }\r\n\r\n // If the ring is bridged, then draw the vertices inside the ring\r\n // using a force based approach\r\n if (ring.isBridged) {\r\n this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength,\r\n this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration,\r\n this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);\r\n ring.positioned = true;\r\n\r\n // Update the center of the bridged ring\r\n this.setRingCenter(ring);\r\n center = ring.center;\r\n\r\n // Setting the centers for the subrings\r\n for (let i = 0; i < ring.rings.length; i++) {\r\n this.setRingCenter(ring.rings[i]);\r\n }\r\n } else {\r\n ring.eachMember(this.graph.vertices, function (v) {\r\n let vertex = that.graph.vertices[v];\r\n\r\n if (!vertex.positioned) {\r\n vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);\r\n }\r\n\r\n a += angle;\r\n\r\n if (!ring.isBridged || ring.rings.length < 3) {\r\n vertex.angle = a;\r\n vertex.positioned = true;\r\n }\r\n }, startVertexId, (previousVertex) ? previousVertex.id : null);\r\n }\r\n\r\n ring.positioned = true;\r\n ring.center = center;\r\n\r\n // Draw neighbours in decreasing order of connectivity\r\n for (let i = 0; i < orderedNeighbours.length; i++) {\r\n let neighbour = this.getRing(orderedNeighbours[i].neighbour);\r\n\r\n if (neighbour.positioned) {\r\n continue;\r\n }\r\n\r\n let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);\r\n\r\n if (vertices.length === 2) {\r\n // This ring is a fused ring\r\n ring.isFused = true;\r\n neighbour.isFused = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n let vertexB = this.graph.vertices[vertices[1]];\r\n\r\n // Get middle between vertex A and B\r\n let midpoint = Vector2.midpoint(vertexA.position, vertexB.position);\r\n\r\n // Get the normals to the line between A and B\r\n let normals = Vector2.normals(vertexA.position, vertexB.position);\r\n\r\n // Normalize the normals\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n // Set length from middle of side to center (the apothem)\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n let apothem = MathHelper.apothem(r, neighbour.getSize());\r\n\r\n normals[0].multiplyScalar(apothem).add(midpoint);\r\n normals[1].multiplyScalar(apothem).add(midpoint);\r\n\r\n // Pick the normal which results in a larger distance to the previous center\r\n // Also check whether it's inside another ring\r\n let nextCenter = normals[0];\r\n if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {\r\n nextCenter = normals[1];\r\n }\r\n\r\n // Get the vertex (A or B) which is in clock-wise direction of the other\r\n let posA = Vector2.subtract(vertexA.position, nextCenter);\r\n let posB = Vector2.subtract(vertexB.position, nextCenter);\r\n\r\n if (posA.clockwise(posB) === -1) {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA, vertexB);\r\n }\r\n } else {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexB, vertexA);\r\n }\r\n }\r\n } else if (vertices.length === 1) {\r\n // This ring is a spiro\r\n ring.isSpiro = true;\r\n neighbour.isSpiro = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n\r\n // Get the vector pointing from the shared vertex to the new centpositioner\r\n let nextCenter = Vector2.subtract(center, vertexA.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n // Get the distance from the vertex to the center\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertexA.position);\r\n\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA);\r\n }\r\n }\r\n }\r\n\r\n // Next, draw atoms that are not part of a ring that are directly attached to this ring\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let ringMember = this.graph.vertices[ring.members[i]];\r\n let ringMemberNeighbours = ringMember.neighbours;\r\n\r\n // If there are multiple, the ovlerap will be resolved in the appropriate step\r\n for (let j = 0; j < ringMemberNeighbours.length; j++) {\r\n let v = this.graph.vertices[ringMemberNeighbours[j]];\r\n\r\n if (v.positioned) {\r\n continue;\r\n }\r\n\r\n v.value.isConnectedToRing = true;\r\n this.createNextBond(v, ringMember, 0.0);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Rotate an entire subtree by an angle around a center.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree that is to rotate.\r\n * @param {Number} angle An angle in randians.\r\n * @param {Vector2} center The rotational center.\r\n */\r\n rotateSubtree(vertexId, parentVertexId, angle, center) {\r\n let that = this;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n vertex.position.rotateAround(angle, center);\r\n\r\n for (var i = 0; i < vertex.value.anchoredRings.length; i++) {\r\n let ring = that.rings[vertex.value.anchoredRings[i]];\r\n\r\n if (ring) {\r\n ring.center.rotateAround(angle, center);\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Gets the overlap score of a subtree.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree.\r\n * @param {Number[]} vertexOverlapScores An array containing the vertex overlap scores indexed by vertex id.\r\n * @returns {Object} An object containing the total overlap score and the center of mass of the subtree weighted by overlap score { value: 0.2, center: new Vector2() }.\r\n */\r\n getSubtreeOverlapScore(vertexId, parentVertexId, vertexOverlapScores) {\r\n let that = this;\r\n let score = 0;\r\n let center = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n if (!vertex.value.isDrawn) {\r\n return;\r\n }\r\n\r\n let s = vertexOverlapScores[vertex.id];\r\n if (s > that.opts.overlapSensitivity) {\r\n score += s;\r\n count++;\r\n }\r\n\r\n let position = that.graph.vertices[vertex.id].position.clone();\r\n position.multiplyScalar(s);\r\n center.add(position);\r\n });\r\n\r\n center.divide(score);\r\n\r\n return {\r\n value: score / count,\r\n center: center\r\n };\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass.\r\n *\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMass() {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass in the neighbourhood of a given position.\r\n *\r\n * @param {Vector2} vec The point at which to look for neighbours.\r\n * @param {Number} [r=currentBondLength*2.0] The radius of vertices to include.\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMassInNeigbourhood(vec, r = this.opts.bondLength * 2.0) {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n let rSq = r * r;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned && vec.distanceSq(vertex.position) < rSq) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Resolve primary (exact) overlaps, such as two vertices that are connected to the same ring vertex.\r\n */\r\n resolvePrimaryOverlaps() {\r\n let overlaps = Array();\r\n let done = Array(this.graph.vertices.length);\r\n\r\n // Looking for overlaps created by two bonds coming out of a ring atom, which both point straight\r\n // away from the ring and are thus perfectly overlapping.\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n let vertex = this.graph.vertices[ring.members[j]];\r\n\r\n if (done[vertex.id]) {\r\n continue;\r\n }\r\n\r\n done[vertex.id] = true;\r\n\r\n let nonRingNeighbours = this.getNonRingNeighbours(vertex.id);\r\n\r\n if (nonRingNeighbours.length > 1) {\r\n // Look for rings where there are atoms with two bonds outside the ring (overlaps)\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n } else if (nonRingNeighbours.length === 1 && vertex.value.rings.length === 2) {\r\n // Look for bonds coming out of joined rings to adjust the angle, an example is: C1=CC(=CC=C1)[C@]12SCCN1CC1=CC=CC=C21\r\n // where the angle has to be adjusted to account for fused ring\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (let i = 0; i < overlaps.length; i++) {\r\n let overlap = overlaps[i];\r\n\r\n if (overlap.vertices.length === 2) {\r\n let a = overlap.vertices[0];\r\n let b = overlap.vertices[1];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let angle = (2 * Math.PI - this.getRing(overlap.rings[0]).getAngle()) / 6.0;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -angle, overlap.common.position);\r\n\r\n // Decide which way to rotate the vertices depending on the effect it has on the overlap score\r\n let overlapScore = this.getOverlapScore();\r\n let subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n let subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n let total = subTreeOverlapA.value + subTreeOverlapB.value;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n\r\n overlapScore = this.getOverlapScore();\r\n subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n\r\n if (subTreeOverlapA.value + subTreeOverlapB.value > total) {\r\n this.rotateSubtree(a.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n }\r\n } else if (overlap.vertices.length === 1) {\r\n if (overlap.rings.length === 2) {\r\n // TODO: Implement for more overlap resolution\r\n // console.log(overlap);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resolve secondary overlaps. Those overlaps are due to the structure turning back on itself.\r\n *\r\n * @param {Object[]} scores An array of objects sorted descending by score.\r\n * @param {Number} scores[].id A vertex id.\r\n * @param {Number} scores[].score The overlap score associated with the vertex id.\r\n */\r\n resolveSecondaryOverlaps(scores) {\r\n for (let i = 0; i < scores.length; i++) {\r\n if (scores[i].score > this.opts.overlapSensitivity) {\r\n let vertex = this.graph.vertices[scores[i].id];\r\n\r\n if (vertex.isTerminal()) {\r\n let closest = this.getClosestVertex(vertex);\r\n\r\n if (closest) {\r\n // If one of the vertices is the first one, the previous vertex is not the central vertex but the dummy\r\n // so take the next rather than the previous, which is vertex 1\r\n let closestPosition = null;\r\n\r\n if (closest.isTerminal()) {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.previousPosition\r\n } else {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.position\r\n }\r\n\r\n let vertexPreviousPosition = vertex.id === 0 ? this.graph.vertices[1].position : vertex.previousPosition;\r\n\r\n vertex.position.rotateAwayFrom(closestPosition, vertexPreviousPosition, MathHelper.toRad(20));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the last non-null or 0 angle vertex.\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex} The last vertex with an angle that was not 0 or null.\r\n */\r\n getLastVertexWithAngle(vertexId) {\r\n let angle = 0;\r\n let vertex = null;\r\n\r\n while (!angle && vertexId) {\r\n vertex = this.graph.vertices[vertexId];\r\n angle = vertex.angle;\r\n vertexId = vertex.parentVertexId;\r\n }\r\n\r\n return vertex;\r\n }\r\n\r\n /**\r\n * Positiones the next vertex thus creating a bond.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @param {Vertex} [previousVertex=null] The previous vertex which has been positioned.\r\n * @param {Number} [angle=0.0] The (global) angle of the vertex.\r\n * @param {Boolean} [originShortest=false] Whether the origin is the shortest subtree in the branch.\r\n * @param {Boolean} [skipPositioning=false] Whether or not to skip positioning and just check the neighbours.\r\n */\r\n createNextBond(vertex, previousVertex = null, angle = 0.0, originShortest = false, skipPositioning = false) {\r\n if (vertex.positioned && !skipPositioning) {\r\n return;\r\n }\r\n\r\n // If the double bond config was set on this vertex, do not check later\r\n let doubleBondConfigSet = false;\r\n\r\n // Keeping track of configurations around double bonds\r\n if (previousVertex) {\r\n let edge = this.graph.getEdge(vertex.id, previousVertex.id);\r\n\r\n if ((edge.bondType === '/' || edge.bondType === '\\\\') && ++this.doubleBondConfigCount % 2 === 1) {\r\n if (this.doubleBondConfig === null) {\r\n this.doubleBondConfig = edge.bondType;\r\n doubleBondConfigSet = true;\r\n\r\n // Switch if the bond is a branch bond and previous vertex is the first\r\n // TODO: Why is it different with the first vertex?\r\n if (previousVertex.parentVertexId === null && vertex.value.branchBond) {\r\n if (this.doubleBondConfig === '/') {\r\n this.doubleBondConfig = '\\\\';\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n this.doubleBondConfig = '/';\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If the current node is the member of one ring, then point straight away\r\n // from the center of the ring. However, if the current node is a member of\r\n // two rings, point away from the middle of the centers of the two rings\r\n if (!skipPositioning) {\r\n if (!previousVertex) {\r\n // Add a (dummy) previous position if there is no previous vertex defined\r\n // Since the first vertex is at (0, 0), create a vector at (bondLength, 0)\r\n // and rotate it by 90°\r\n\r\n let dummy = new Vector2(this.opts.bondLength, 0);\r\n dummy.rotate(MathHelper.toRad(-60));\r\n\r\n vertex.previousPosition = dummy;\r\n vertex.setPosition(this.opts.bondLength, 0);\r\n vertex.angle = MathHelper.toRad(-60);\r\n\r\n // Do not position the vertex if it belongs to a bridged ring that is positioned using a layout algorithm.\r\n if (vertex.value.bridgedRing === null) {\r\n vertex.positioned = true;\r\n }\r\n } else if (previousVertex.value.rings.length > 0) {\r\n let neighbours = previousVertex.neighbours;\r\n let joinedVertex = null;\r\n let pos = new Vector2(0.0, 0.0);\r\n\r\n if (previousVertex.value.bridgedRing === null && previousVertex.value.rings.length > 1) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n if (ArrayHelper.containsAll(neighbour.value.rings, previousVertex.value.rings)) {\r\n joinedVertex = neighbour;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (joinedVertex === null) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let v = this.graph.vertices[neighbours[i]];\r\n\r\n if (v.positioned && this.areVerticesInSameRing(v, previousVertex)) {\r\n pos.add(Vector2.subtract(v.position, previousVertex.position));\r\n }\r\n }\r\n\r\n pos.invert().normalize().multiplyScalar(this.opts.bondLength).add(previousVertex.position);\r\n } else {\r\n pos = joinedVertex.position.clone().rotateAround(Math.PI, previousVertex.position);\r\n }\r\n\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.setPositionFromVector(pos);\r\n vertex.positioned = true;\r\n } else {\r\n // If the previous vertex was not part of a ring, draw a bond based\r\n // on the global angle of the previous bond\r\n let v = new Vector2(this.opts.bondLength, 0);\r\n\r\n v.rotate(angle);\r\n v.add(previousVertex.position);\r\n\r\n vertex.setPositionFromVector(v);\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.positioned = true;\r\n }\r\n }\r\n\r\n // Go to next vertex\r\n // If two rings are connected by a bond ...\r\n if (vertex.value.bridgedRing !== null) {\r\n let nextRing = this.getRing(vertex.value.bridgedRing);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.members.length);\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else if (vertex.value.rings.length > 0) {\r\n let nextRing = this.getRing(vertex.value.rings[0]);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else {\r\n // Draw the non-ring vertices connected to this one\r\n let isStereoCenter = vertex.value.isStereoCenter;\r\n let tmpNeighbours = vertex.getNeighbours();\r\n let neighbours = Array();\r\n\r\n // Remove neighbours that are not drawn\r\n for (let i = 0; i < tmpNeighbours.length; i++) {\r\n if (this.graph.vertices[tmpNeighbours[i]].value.isDrawn) {\r\n neighbours.push(tmpNeighbours[i]);\r\n }\r\n }\r\n\r\n // Remove the previous vertex (which has already been drawn)\r\n if (previousVertex) {\r\n neighbours = ArrayHelper.remove(neighbours, previousVertex.id);\r\n }\r\n\r\n let previousAngle = vertex.getAngle();\r\n\r\n if (neighbours.length === 1) {\r\n let nextVertex = this.graph.vertices[neighbours[0]];\r\n\r\n // Make a single chain always cis except when there's a tribble (yes, this is a Star Trek reference) bond\r\n // or if there are successive double bonds. Added a ring check because if there is an aromatic ring the ring bond inside the ring counts as a double bond and leads to =-= being straight.\r\n if ((vertex.value.bondType === '#' || (previousVertex && previousVertex.value.bondType === '#')) ||\r\n vertex.value.bondType === '=' && previousVertex && previousVertex.value.rings.length === 0 &&\r\n previousVertex.value.bondType === '=' && vertex.value.branchBond !== '-') {\r\n vertex.value.drawExplicit = false;\r\n\r\n if (previousVertex) {\r\n let straightEdge1 = this.graph.getEdge(vertex.id, previousVertex.id);\r\n straightEdge1.center = true;\r\n }\r\n\r\n let straightEdge2 = this.graph.getEdge(vertex.id, nextVertex.id);\r\n straightEdge2.center = true;\r\n\r\n if (vertex.value.bondType === '#' || previousVertex && previousVertex.value.bondType === '#') {\r\n nextVertex.angle = 0.0;\r\n }\r\n\r\n nextVertex.drawExplicit = true;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else if (previousVertex && previousVertex.value.rings.length > 0) {\r\n // If coming out of a ring, always draw away from the center of mass\r\n let proposedAngleA = MathHelper.toRad(60);\r\n let proposedAngleB = -proposedAngleA;\r\n\r\n let proposedVectorA = new Vector2(this.opts.bondLength, 0);\r\n let proposedVectorB = new Vector2(this.opts.bondLength, 0);\r\n\r\n proposedVectorA.rotate(proposedAngleA).add(vertex.position);\r\n proposedVectorB.rotate(proposedAngleB).add(vertex.position);\r\n\r\n // let centerOfMass = this.getCurrentCenterOfMassInNeigbourhood(vertex.position, 100);\r\n let centerOfMass = this.getCurrentCenterOfMass();\r\n let distanceA = proposedVectorA.distanceSq(centerOfMass);\r\n let distanceB = proposedVectorB.distanceSq(centerOfMass);\r\n\r\n nextVertex.angle = distanceA < distanceB ? proposedAngleB : proposedAngleA;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else {\r\n let a = vertex.angle;\r\n // Take the min and max if the previous angle was in a 4-neighbourhood (90° angles)\r\n // TODO: If a is null or zero, it should be checked whether or not this one should go cis or trans, that is,\r\n // it should go into the oposite direction of the last non-null or 0 previous vertex / angle.\r\n if (previousVertex && previousVertex.neighbours.length > 3) {\r\n if (a > 0) {\r\n a = Math.min(1.0472, a);\r\n } else if (a < 0) {\r\n a = Math.max(-1.0472, a);\r\n } else {\r\n a = 1.0472;\r\n }\r\n } else if (!a) {\r\n let v = this.getLastVertexWithAngle(vertex.id);\r\n a = v.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n }\r\n\r\n // Handle configuration around double bonds\r\n if (previousVertex && !doubleBondConfigSet) {\r\n let bondType = this.graph.getEdge(vertex.id, nextVertex.id).bondType;\r\n\r\n if (bondType === '/') {\r\n if (this.doubleBondConfig === '/') {\r\n // Nothing to do since it will be trans per default\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n a = -a;\r\n }\r\n this.doubleBondConfig = null;\r\n } else if (bondType === '\\\\') {\r\n if (this.doubleBondConfig === '/') {\r\n a = -a;\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n // Nothing to do since it will be trans per default\r\n }\r\n this.doubleBondConfig = null;\r\n }\r\n }\r\n\r\n if (originShortest) {\r\n nextVertex.angle = a;\r\n } else {\r\n nextVertex.angle = -a;\r\n }\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n }\r\n } else if (neighbours.length === 2) {\r\n // If the previous vertex comes out of a ring, it doesn't have an angle set\r\n let a = vertex.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n\r\n // Check for the longer subtree - always go with cis for the longer subtree\r\n let subTreeDepthA = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let subTreeDepthB = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n\r\n let l = this.graph.vertices[neighbours[0]];\r\n let r = this.graph.vertices[neighbours[1]];\r\n\r\n l.value.subtreeDepth = subTreeDepthA;\r\n r.value.subtreeDepth = subTreeDepthB;\r\n\r\n // Also get the subtree for the previous direction (this is important when\r\n // the previous vertex is the shortest path)\r\n let subTreeDepthC = this.graph.getTreeDepth(previousVertex ? previousVertex.id : null, vertex.id);\r\n if (previousVertex) {\r\n previousVertex.value.subtreeDepth = subTreeDepthC;\r\n }\r\n\r\n let cis = 0;\r\n let trans = 1;\r\n\r\n // Carbons go always cis\r\n if (r.value.element === 'C' && l.value.element !== 'C' && subTreeDepthB > 1 && subTreeDepthA < 5) {\r\n cis = 1;\r\n trans = 0;\r\n } else if (r.value.element !== 'C' && l.value.element === 'C' && subTreeDepthA > 1 && subTreeDepthB < 5) {\r\n cis = 0;\r\n trans = 1;\r\n } else if (subTreeDepthB > subTreeDepthA) {\r\n cis = 1;\r\n trans = 0;\r\n }\r\n\r\n let cisVertex = this.graph.vertices[neighbours[cis]];\r\n let transVertex = this.graph.vertices[neighbours[trans]];\r\n\r\n // If the origin tree is the shortest, make them the main chain\r\n let originShortest = false;\r\n if (subTreeDepthC < subTreeDepthA && subTreeDepthC < subTreeDepthB) {\r\n originShortest = true;\r\n }\r\n\r\n transVertex.angle = a;\r\n cisVertex.angle = -a;\r\n\r\n if (this.doubleBondConfig === '\\\\') {\r\n if (transVertex.value.branchBond === '\\\\') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n } else if (this.doubleBondConfig === '/') {\r\n if (transVertex.value.branchBond === '/') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n }\r\n\r\n this.createNextBond(transVertex, vertex, previousAngle + transVertex.angle, originShortest);\r\n this.createNextBond(cisVertex, vertex, previousAngle + cisVertex.angle, originShortest);\r\n } else if (neighbours.length === 3) {\r\n // The vertex with the longest sub-tree should always go straight\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n\r\n let s = this.graph.vertices[neighbours[0]];\r\n let l = this.graph.vertices[neighbours[1]];\r\n let r = this.graph.vertices[neighbours[2]];\r\n\r\n s.value.subtreeDepth = d1;\r\n l.value.subtreeDepth = d2;\r\n r.value.subtreeDepth = d3;\r\n\r\n if (d2 > d1 && d2 > d3) {\r\n s = this.graph.vertices[neighbours[1]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[2]];\r\n } else if (d3 > d1 && d3 > d2) {\r\n s = this.graph.vertices[neighbours[2]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[1]];\r\n }\r\n\r\n // Create a cross if more than one subtree is of length > 1\r\n // or the vertex is connected to a ring\r\n if (previousVertex &&\r\n previousVertex.value.rings.length < 1 &&\r\n s.value.rings.length < 1 &&\r\n l.value.rings.length < 1 &&\r\n r.value.rings.length < 1 &&\r\n this.graph.getTreeDepth(l.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(r.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(s.id, vertex.id) > 1) {\r\n\r\n s.angle = -vertex.angle;\r\n if (vertex.angle >= 0) {\r\n l.angle = MathHelper.toRad(30);\r\n r.angle = MathHelper.toRad(90);\r\n } else {\r\n l.angle = -MathHelper.toRad(30);\r\n r.angle = -MathHelper.toRad(90);\r\n }\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n } else {\r\n s.angle = 0.0;\r\n l.angle = MathHelper.toRad(90);\r\n r.angle = -MathHelper.toRad(90);\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n }\r\n } else if (neighbours.length === 4) {\r\n // The vertex with the longest sub-tree should always go to the reflected opposide direction\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n let d4 = this.graph.getTreeDepth(neighbours[3], vertex.id);\r\n\r\n let w = this.graph.vertices[neighbours[0]];\r\n let x = this.graph.vertices[neighbours[1]];\r\n let y = this.graph.vertices[neighbours[2]];\r\n let z = this.graph.vertices[neighbours[3]];\r\n\r\n w.value.subtreeDepth = d1;\r\n x.value.subtreeDepth = d2;\r\n y.value.subtreeDepth = d3;\r\n z.value.subtreeDepth = d4;\r\n\r\n if (d2 > d1 && d2 > d3 && d2 > d4) {\r\n w = this.graph.vertices[neighbours[1]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[2]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d3 > d1 && d3 > d2 && d3 > d4) {\r\n w = this.graph.vertices[neighbours[2]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d4 > d1 && d4 > d2 && d4 > d3) {\r\n w = this.graph.vertices[neighbours[3]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[2]];\r\n }\r\n\r\n w.angle = -MathHelper.toRad(36);\r\n x.angle = MathHelper.toRad(36);\r\n y.angle = -MathHelper.toRad(108);\r\n z.angle = MathHelper.toRad(108);\r\n\r\n this.createNextBond(w, vertex, previousAngle + w.angle);\r\n this.createNextBond(x, vertex, previousAngle + x.angle);\r\n this.createNextBond(y, vertex, previousAngle + y.angle);\r\n this.createNextBond(z, vertex, previousAngle + z.angle);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Gets the vetex sharing the edge that is the common bond of two rings.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {(Number|null)} The id of a vertex sharing the edge that is the common bond of two rings with the vertex provided or null, if none.\r\n */\r\n getCommonRingbondNeighbour(vertex) {\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n\r\n if (ArrayHelper.containsAll(neighbour.value.rings, vertex.value.rings)) {\r\n return neighbour;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Check if a vector is inside any ring.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Boolean} A boolean indicating whether or not the point (vector) is inside any of the rings associated with the current molecule.\r\n */\r\n isPointInRing(vec) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (!ring.positioned) {\r\n continue;\r\n }\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let radiusSq = radius * radius;\r\n\r\n if (vec.distanceSq(ring.center) < radiusSq) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is part of a ring.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is part of a ring.\r\n */\r\n isEdgeInRing(edge) {\r\n let source = this.graph.vertices[edge.sourceId];\r\n let target = this.graph.vertices[edge.targetId];\r\n\r\n return this.areVerticesInSameRing(source, target);\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is rotatable.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is rotatable.\r\n */\r\n isEdgeRotatable(edge) {\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n\r\n // Only single bonds are rotatable\r\n if (edge.bondType !== '-') {\r\n return false;\r\n }\r\n\r\n // Do not rotate edges that have a further single bond to each side - do that!\r\n // If the bond is terminal, it doesn't make sense to rotate it\r\n // if (vertexA.getNeighbourCount() + vertexB.getNeighbourCount() < 5) {\r\n // return false;\r\n // }\r\n\r\n if (vertexA.isTerminal() || vertexB.isTerminal()) {\r\n return false;\r\n }\r\n\r\n // Ringbonds are not rotatable\r\n return !(vertexA.value.rings.length > 0 && vertexB.value.rings.length > 0 && this.areVerticesInSameRing(vertexA, vertexB));\r\n }\r\n\r\n /**\r\n * Check whether or not a ring is an implicitly defined aromatic ring (lower case smiles).\r\n *\r\n * @param {Ring} ring A ring.\r\n * @returns {Boolean} A boolean indicating whether or not a ring is implicitly defined as aromatic.\r\n */\r\n isRingAromatic(ring) {\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let vertex = this.graph.vertices[ring.members[i]];\r\n\r\n if (!vertex.value.isPartOfAromaticRing) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the normals of an edge.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Vector2[]} An array containing two vectors, representing the normals.\r\n */\r\n getEdgeNormals(edge) {\r\n let v1 = this.graph.vertices[edge.sourceId].position;\r\n let v2 = this.graph.vertices[edge.targetId].position;\r\n\r\n // Get the normalized normals for the edge\r\n return Vector2.units(v1, v2);\r\n }\r\n\r\n /**\r\n * Returns an array of vertices that are neighbouring a vertix but are not members of a ring (including bridges).\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex[]} An array of vertices.\r\n */\r\n getNonRingNeighbours(vertexId) {\r\n let nrneighbours = Array();\r\n let vertex = this.graph.vertices[vertexId];\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n let nIntersections = ArrayHelper.intersection(vertex.value.rings, neighbour.value.rings).length;\r\n\r\n if (nIntersections === 0 && neighbour.value.isBridge == false) {\r\n nrneighbours.push(neighbour);\r\n }\r\n }\r\n\r\n return nrneighbours;\r\n }\r\n\r\n /**\r\n * Annotaed stereochemistry information for visualization.\r\n */\r\n annotateStereochemistry() {\r\n let maxDepth = 10;\r\n\r\n // For each stereo-center\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (!vertex.value.isStereoCenter) {\r\n continue;\r\n }\r\n\r\n let neighbours = vertex.getNeighbours();\r\n let nNeighbours = neighbours.length;\r\n let priorities = Array(nNeighbours);\r\n\r\n for (let j = 0; j < nNeighbours; j++) {\r\n let visited = new Uint8Array(this.graph.vertices.length);\r\n let priority = Array(Array());\r\n visited[vertex.id] = 1;\r\n\r\n this.visitStereochemistry(neighbours[j], vertex.id, visited, priority, maxDepth, 0);\r\n\r\n // Sort each level according to atomic number\r\n for (let k = 0; k < priority.length; k++) {\r\n priority[k].sort(function (a, b) {\r\n return b - a\r\n });\r\n }\r\n\r\n priorities[j] = [j, priority];\r\n }\r\n\r\n let maxLevels = 0;\r\n let maxEntries = 0;\r\n for (let j = 0; j < priorities.length; j++) {\r\n if (priorities[j][1].length > maxLevels) {\r\n maxLevels = priorities[j][1].length;\r\n }\r\n\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n if (priorities[j][1][k].length > maxEntries) {\r\n maxEntries = priorities[j][1][k].length;\r\n }\r\n }\r\n }\r\n\r\n for (let j = 0; j < priorities.length; j++) {\r\n let diff = maxLevels - priorities[j][1].length;\r\n for (let k = 0; k < diff; k++) {\r\n priorities[j][1].push([]);\r\n }\r\n\r\n // Break ties by the position in the SMILES string as per specification\r\n priorities[j][1].push([neighbours[j]]);\r\n\r\n // Make all same length. Fill with zeroes.\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n let diff = maxEntries - priorities[j][1][k].length;\r\n\r\n for (let l = 0; l < diff; l++) {\r\n priorities[j][1][k].push(0);\r\n }\r\n }\r\n }\r\n\r\n priorities.sort(function (a, b) {\r\n for (let j = 0; j < a[1].length; j++) {\r\n for (let k = 0; k < a[1][j].length; k++) {\r\n if (a[1][j][k] > b[1][j][k]) {\r\n return -1;\r\n } else if (a[1][j][k] < b[1][j][k]) {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n\r\n let order = new Uint8Array(nNeighbours);\r\n for (let j = 0; j < nNeighbours; j++) {\r\n order[j] = priorities[j][0];\r\n vertex.value.priority = j;\r\n }\r\n\r\n // Check the angles between elements 0 and 1, and 0 and 2 to determine whether they are\r\n // drawn cw or ccw\r\n // TODO: OC(Cl)=[C@]=C(C)F currently fails here, however this is, IMHO, not a valid SMILES.\r\n let posA = this.graph.vertices[neighbours[order[0]]].position;\r\n let posB = this.graph.vertices[neighbours[order[1]]].position;\r\n\r\n let cwA = posA.relativeClockwise(posB, vertex.position);\r\n\r\n // If the second priority is clockwise from the first, the ligands are drawn clockwise, since\r\n // The hydrogen can be drawn on either side\r\n let isCw = cwA === -1;\r\n\r\n let rotation = vertex.value.bracket.chirality === '@' ? -1 : 1;\r\n let rs = MathHelper.parityOfPermutation(order) * rotation === 1 ? 'R' : 'S';\r\n\r\n // Flip the hydrogen direction when the drawing doesn't match the chirality.\r\n let wedgeA = 'down';\r\n let wedgeB = 'up';\r\n if (isCw && rs !== 'R' || !isCw && rs !== 'S') {\r\n vertex.value.hydrogenDirection = 'up';\r\n wedgeA = 'up';\r\n wedgeB = 'down';\r\n }\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, neighbours[order[order.length - 1]]).wedge = wedgeA;\r\n }\r\n\r\n // Get the shortest subtree to flip up / down. Ignore lowest priority\r\n // The rules are following:\r\n // 1. Do not draw wedge between two stereocenters\r\n // 2. Heteroatoms\r\n // 3. Draw outside ring\r\n // 4. Shortest subtree\r\n\r\n let wedgeOrder = new Array(neighbours.length - 1);\r\n let showHydrogen = vertex.value.rings.length > 1 && vertex.value.hasHydrogen;\r\n let offset = vertex.value.hasHydrogen ? 1 : 0;\r\n\r\n for (let j = 0; j < order.length - offset; j++) {\r\n wedgeOrder[j] = new Uint32Array(2);\r\n let neighbour = this.graph.vertices[neighbours[order[j]]];\r\n wedgeOrder[j][0] += neighbour.value.isStereoCenter ? 0 : 100000;\r\n // wedgeOrder[j][0] += neighbour.value.rings.length > 0 ? 0 : 10000;\r\n // Only add if in same ring, unlike above\r\n wedgeOrder[j][0] += this.areVerticesInSameRing(neighbour, vertex) ? 0 : 10000;\r\n wedgeOrder[j][0] += neighbour.value.isHeteroAtom() ? 1000 : 0;\r\n wedgeOrder[j][0] -= neighbour.value.subtreeDepth === 0 ? 1000 : 0;\r\n wedgeOrder[j][0] += 1000 - neighbour.value.subtreeDepth;\r\n wedgeOrder[j][1] = neighbours[order[j]];\r\n }\r\n\r\n\r\n wedgeOrder.sort(function (a, b) {\r\n if (a[0] > b[0]) {\r\n return -1;\r\n } else if (a[0] < b[0]) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n\r\n // If all neighbours are in a ring, do not draw wedge, the hydrogen will be drawn.\r\n if (!showHydrogen) {\r\n let wedgeId = wedgeOrder[0][1];\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedgeB;\r\n } else {\r\n let wedge = wedgeB;\r\n\r\n for (let j = order.length - 1; j >= 0; j--) {\r\n if (wedge === wedgeA) {\r\n wedge = wedgeB;\r\n } else {\r\n wedge = wedgeA;\r\n }\r\n if (neighbours[order[j]] === wedgeId) {\r\n break;\r\n }\r\n }\r\n\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedge;\r\n }\r\n }\r\n\r\n vertex.value.chirality = rs;\r\n }\r\n }\r\n\r\n /**\r\n *\r\n *\r\n * @param {Number} vertexId The id of a vertex.\r\n * @param {(Number|null)} previousVertexId The id of the parent vertex of the vertex.\r\n * @param {Uint8Array} visited An array containing the visited flag for all vertices in the graph.\r\n * @param {Array} priority An array of arrays storing the atomic numbers for each level.\r\n * @param {Number} maxDepth The maximum depth.\r\n * @param {Number} depth The current depth.\r\n * @param {Number} parentAtomicNumber\r\n */\r\n visitStereochemistry(vertexId, previousVertexId, visited, priority, maxDepth, depth, parentAtomicNumber = 0) {\r\n visited[vertexId] = 1;\r\n let vertex = this.graph.vertices[vertexId];\r\n let atomicNumber = vertex.value.getAtomicNumber();\r\n\r\n if (priority.length <= depth) {\r\n priority.push(Array());\r\n }\r\n\r\n for (let i = 0; i < this.graph.getEdge(vertexId, previousVertexId).weight; i++) {\r\n priority[depth].push(parentAtomicNumber * 1000 + atomicNumber);\r\n }\r\n\r\n let neighbours = this.graph.vertices[vertexId].neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (visited[neighbours[i]] !== 1 && depth < maxDepth - 1) {\r\n this.visitStereochemistry(neighbours[i], vertexId, visited.slice(), priority, maxDepth, depth + 1, atomicNumber);\r\n }\r\n }\r\n\r\n // Valences are filled with hydrogens and passed to the next level.\r\n if (depth < maxDepth - 1) {\r\n let bonds = 0;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n bonds += this.graph.getEdge(vertexId, neighbours[i]).weight;\r\n }\r\n\r\n for (let i = 0; i < vertex.value.getMaxBonds() - bonds; i++) {\r\n if (priority.length <= depth + 1) {\r\n priority.push(Array());\r\n }\r\n\r\n priority[depth + 1].push(atomicNumber * 1000 + 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Creates pseudo-elements (such as Et, Me, Ac, Bz, ...) at the position of the carbon sets\r\n * the involved atoms not to be displayed.\r\n */\r\n initPseudoElements() {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n // Ignore atoms that have less than 3 neighbours, except if\r\n // the vertex is connected to a ring and has two neighbours\r\n if (vertex.getNeighbourCount() < 3 || vertex.value.rings.length > 0) {\r\n continue;\r\n }\r\n\r\n // TODO: This exceptions should be handled more elegantly (via config file?)\r\n\r\n // Ignore phosphates (especially for triphosphates)\r\n if (vertex.value.element === 'P') {\r\n continue;\r\n }\r\n\r\n // Ignore also guanidine\r\n if (vertex.value.element === 'C' && neighbours.length === 3 &&\r\n neighbours[0].value.element === 'N' && neighbours[1].value.element === 'N' && neighbours[2].value.element === 'N') {\r\n continue;\r\n }\r\n\r\n // Continue if there are less than two heteroatoms\r\n // or if a neighbour has more than 1 neighbour\r\n let heteroAtomCount = 0;\r\n let ctn = 0;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n let neighbouringElement = neighbour.value.element;\r\n let neighbourCount = neighbour.getNeighbourCount();\r\n\r\n if (neighbouringElement !== 'C' && neighbouringElement !== 'H' &&\r\n neighbourCount === 1) {\r\n heteroAtomCount++;\r\n }\r\n\r\n if (neighbourCount > 1) {\r\n ctn++;\r\n }\r\n }\r\n\r\n if (ctn > 1 || heteroAtomCount < 2) {\r\n continue;\r\n }\r\n\r\n // Get the previous atom (the one which is not terminal)\r\n let previous = null;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n previous = neighbour;\r\n }\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n continue;\r\n }\r\n\r\n neighbour.value.isDrawn = false;\r\n\r\n let hydrogens = Atom.maxBonds[neighbour.value.element] - neighbour.value.bondCount;\r\n let charge = '';\r\n\r\n if (neighbour.value.bracket) {\r\n hydrogens = neighbour.value.bracket.hcount;\r\n charge = neighbour.value.bracket.charge || 0;\r\n }\r\n\r\n vertex.value.attachPseudoElement(neighbour.value.element, previous ? previous.value.element : null, hydrogens, charge);\r\n }\r\n }\r\n\r\n // The second pass\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const atom = vertex.value;\r\n const element = atom.element;\r\n\r\n if (element === 'C' || element === 'H' || !atom.isDrawn) {\r\n continue;\r\n }\r\n\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j].value;\r\n\r\n if (!neighbour.hasAttachedPseudoElements || neighbour.getAttachedPseudoElementsCount() !== 2) {\r\n continue;\r\n }\r\n\r\n const pseudoElements = neighbour.getAttachedPseudoElements();\r\n\r\n if (pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\r\n neighbour.isDrawn = false;\r\n vertex.value.attachPseudoElement('Ac', '', 0);\r\n }\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.graph.getDecays();\r\n }\r\n\r\n buildBlockSmiles() {\r\n return this.graph.buildSmiles();\r\n }\r\n\r\n /**\r\n * Find edge and mark it as decay point and redraw graph\r\n * @param e event\r\n */\r\n handleMouseClick(e) {\r\n if (this.opts.drawDecayPoints === DecayState.VALUES.NO) {\r\n return;\r\n }\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (!this.graph) {\r\n return;\r\n }\r\n this.findAndReDrawEdge(e.clientX - this.opts.offsetX, e.clientY - this.opts.offsetY + (document.documentElement.scrollTop || document.body.scrollTop));\r\n }\r\n\r\n /**\r\n * Find edge which was clicked, mark edge as decay point and redraw graph\r\n * @param mouseX mouse positionX - offsetX\r\n * @param mouseY mouse positionY - offsetY\r\n */\r\n findAndReDrawEdge(mouseX, mouseY) {\r\n for (let i = 0; i < this.graph.edges.length; ++i) {\r\n let vertexA = this.graph.vertices[this.graph.edges[i].sourceId];\r\n let vertexB = this.graph.vertices[this.graph.edges[i].targetId];\r\n if (!vertexA || !vertexB) {\r\n continue;\r\n }\r\n let scale = this.computeScale();\r\n let line = new Line(vertexA.position, vertexB.position, null, null, false, false, true);\r\n let l = this.computeEdgeLeftPoint(line, scale);\r\n let r = this.computeEdgeRightPoint(line, scale);\r\n if (mouseX < l.x - this.opts.mouseTolerance || mouseX > r.x + this.opts.mouseTolerance) {\r\n continue;\r\n }\r\n if ((mouseY > l.y - this.opts.mouseTolerance && mouseY < r.y + this.opts.mouseTolerance)\r\n || (mouseY > r.y - this.opts.mouseTolerance && mouseY < l.y + this.opts.mouseTolerance)) {\r\n this.reDrawGraphWithEdgeAsDecay(i);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Make edge decay point and redraw graph\r\n * @param {Number} edgeId\r\n */\r\n reDrawGraphWithEdgeAsDecay(edgeId) {\r\n this.graph.revertEdgeDecayPoint(edgeId);\r\n this.canvasWrapper.updateSize(this.opts.width, this.opts.height);\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n }\r\n\r\n /**\r\n * Compute scale of canvas\r\n * @return {number} scale\r\n */\r\n computeScale() {\r\n let scaleX = this.canvasWrapper.canvas.offsetWidth / this.canvasWrapper.drawingWidth;\r\n let scaleY = this.canvasWrapper.canvas.offsetHeight / this.canvasWrapper.drawingHeight;\r\n return (scaleX < scaleY) ? scaleX : scaleY;\r\n }\r\n\r\n /**\r\n * Compute left point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeLeftPoint(line, scale) {\r\n return this.computeEdgePoint(line.getLeftVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute right point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeRightPoint(line, scale) {\r\n return this.computeEdgePoint(line.getRightVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute point coordinates for compare\r\n * add offset to coordinates and multiply coordinates with scale\r\n * @param {Vector2} point\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgePoint(point, scale) {\r\n point.x += this.canvasWrapper.offsetX;\r\n point.y += this.canvasWrapper.offsetY;\r\n point.x *= scale;\r\n point.y *= scale;\r\n return point;\r\n }\r\n}\r\n\r\nmodule.exports = Drawer;\r\n","//@ts-check\r\n\r\n/** \r\n * A class representing an edge. \r\n * \r\n * @property {Number} id The id of this edge.\r\n * @property {Number} sourceId The id of the source vertex.\r\n * @property {Number} targetId The id of the target vertex.\r\n * @property {Number} weight The weight of this edge. That is, the degree of the bond (single bond = 1, double bond = 2, etc).\r\n * @property {String} [bondType='-'] The bond type of this edge.\r\n * @property {Boolean} [isPartOfAromaticRing=false] Whether or not this edge is part of an aromatic ring.\r\n * @property {Boolean} [center=false] Wheter or not the bond is centered. For example, this affects straight double bonds.\r\n * @property {String} [wedge=''] Wedge direction. Either '', 'up' or 'down'\r\n */\r\nclass Edge {\r\n /**\r\n * The constructor for the class Edge.\r\n *\r\n * @param {Number} sourceId A vertex id.\r\n * @param {Number} targetId A vertex id.\r\n * @param {Number} [weight=1] The weight of the edge.\r\n */\r\n constructor(sourceId, targetId, weight = 1) {\r\n this.id = null;\r\n this.sourceId = sourceId;\r\n this.targetId = targetId;\r\n this.weight = weight;\r\n this.bondType = '-';\r\n this.isPartOfAromaticRing = false;\r\n this.center = false;\r\n this.wedge = '';\r\n this.isDecay = false;\r\n this.isDecayAll = false;\r\n }\r\n\r\n /**\r\n * Set the bond type of this edge. This also sets the edge weight.\r\n * @param {String} bondType \r\n */\r\n setBondType(bondType) {\r\n this.bondType = bondType;\r\n this.weight = Edge.bonds[bondType];\r\n }\r\n\r\n /**\r\n * Set decay\r\n * @param {Boolean} decay point\r\n */\r\n setDecay(decay) {\r\n this.isDecay = decay;\r\n }\r\n\r\n /**\r\n * Set decay All\r\n * @param {Boolean} decay point\r\n */\r\n setDecayAll(decay) {\r\n this.isDecayAll = decay;\r\n }\r\n\r\n /**\r\n * An object mapping the bond type to the number of bonds.\r\n *\r\n * @returns {Object} The object containing the map.\r\n */\r\n static get bonds() {\r\n return {\r\n '-': 1,\r\n '/': 1,\r\n '\\\\': 1,\r\n '=': 2,\r\n '#': 3,\r\n '$': 4\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Edge;\r\n","//@ts-check\r\nconst DecayPoint = require('./DecayPoint');\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Ring = require('./Ring');\r\nconst Atom = require('./Atom');\r\nconst VertexState = require('./VertexState');\r\nconst SmallGraph = require('./SmallGraph');\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst DecayState = require('./DecayState');\r\nconst MutableBoolean = require('./MutableBoolean');\r\nconst MutableCounter = require('./MutableCounter');\r\nconst Direction = require('./Direction');\r\n\r\n/**\r\n * A class representing the molecular graph.\r\n *\r\n * @property {Vertex[]} vertices The vertices of the graph.\r\n * @property {Edge[]} edges The edges of this graph.\r\n * @property {Number[]} decays The id of edges marked as decay point of this graph.\r\n * @property {Object} vertexIdsToEdgeId A map mapping vertex ids to the edge between the two vertices. The key is defined as vertexAId + '_' + vertexBId.\r\n * @property {Boolean} isometric A boolean indicating whether or not the SMILES associated with this graph is isometric.\r\n */\r\nclass Graph {\r\n /**\r\n * The constructor of the class Graph.\r\n *\r\n * @param {Object} parseTree A SMILES parse tree.\r\n * @param {Boolean} [isomeric=false] A boolean specifying whether or not the SMILES is isomeric.\r\n * @param options\r\n */\r\n constructor(parseTree, isomeric = false, options = {}) {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.decays = Array();\r\n this.decaysAll = Array();\r\n this.vertexIdsToEdgeId = {};\r\n this.isomeric = isomeric;\r\n this._startingVertexes = [];\r\n this._isCyclic = false;\r\n this._polyketide = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.options = options;\r\n this._componentsIsPolyketide = [];\r\n\r\n // Used for the bridge detection algorithm\r\n this._time = 0;\r\n this._init(parseTree);\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION. Initializing the graph from the parse tree.\r\n *\r\n * @param {Object} node The current node in the parse tree.\r\n * @param order\r\n * @param {Number} parentVertexId=null The id of the previous vertex.\r\n * @param {Boolean} isBranch=false Whether or not the bond leading to this vertex is a branch bond. Branches are represented by parentheses in smiles (e.g. CC(O)C).\r\n */\r\n _init(node, order = 0, parentVertexId = null, isBranch = false) {\r\n // Create a new vertex object\r\n let atom = new Atom(node.atom.element ? node.atom.element : node.atom, node.bond);\r\n\r\n atom.branchBond = node.branchBond;\r\n atom.ringbonds = node.ringbonds;\r\n atom.bracket = node.atom.element ? node.atom : null;\r\n\r\n let vertex = new Vertex(atom);\r\n let parentVertex = this.vertices[parentVertexId];\r\n\r\n this.addVertex(vertex);\r\n\r\n // Add the id of this node to the parent as child\r\n if (parentVertexId !== null) {\r\n vertex.setParentVertexId(parentVertexId);\r\n vertex.value.addNeighbouringElement(parentVertex.value.element);\r\n parentVertex.addChild(vertex.id);\r\n parentVertex.value.addNeighbouringElement(atom.element);\r\n\r\n // In addition create a spanningTreeChildren property, which later will\r\n // not contain the children added through ringbonds\r\n parentVertex.spanningTreeChildren.push(vertex.id);\r\n\r\n // Add edge between this node and its parent\r\n let edge = new Edge(parentVertexId, vertex.id, 1);\r\n let vertexId;\r\n\r\n if (isBranch) {\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n } else {\r\n edge.setBondType(parentVertex.value.bondType || '-');\r\n vertexId = parentVertex.id;\r\n }\r\n\r\n this.addEdge(edge);\r\n }\r\n\r\n let offset = node.ringbondCount + 1;\r\n\r\n if (atom.bracket) {\r\n offset += atom.bracket.hcount;\r\n }\r\n\r\n let stereoHydrogens = 0;\r\n if (atom.bracket && atom.bracket.chirality) {\r\n atom.isStereoCenter = true;\r\n stereoHydrogens = atom.bracket.hcount;\r\n for (var i = 0; i < stereoHydrogens; i++) {\r\n this._init({\r\n atom: 'H',\r\n isBracket: 'false',\r\n branches: Array(),\r\n branchCount: 0,\r\n ringbonds: Array(),\r\n ringbondCount: false,\r\n next: null,\r\n hasNext: false,\r\n bond: '-'\r\n }, i, vertex.id, true);\r\n }\r\n }\r\n\r\n for (var i = 0; i < node.branchCount; i++) {\r\n this._init(node.branches[i], i + offset, vertex.id, true);\r\n }\r\n\r\n if (node.hasNext) {\r\n this._init(node.next, node.branchCount + offset, vertex.id);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of molecule\r\n * Types of decay points, declared in DecayPoint\r\n */\r\n findDecayPoints() {\r\n if (!Object.keys(this.options).length) {\r\n return;\r\n }\r\n\r\n switch (this.options.drawDecayPoints) {\r\n default:\r\n case DecayState.VALUES.NO:\r\n return;\r\n case DecayState.VALUES.STANDARD:\r\n this.standardDecays();\r\n break;\r\n case DecayState.VALUES.SOURCE:\r\n this.sourceDecays();\r\n break;\r\n case DecayState.VALUES.STANDARD_AND_SOURCE:\r\n this.standardDecays();\r\n this.sourceDecays();\r\n break;\r\n }\r\n }\r\n\r\n reduceDecays() {\r\n this._decaysCopy = [];\r\n this.dfsSmilesInitialization();\r\n for (let i = 0; i < this.decays.length; i++) {\r\n this.smallBlockDfsStart(this.edges[this.decays[i]]);\r\n }\r\n this.decays = [];\r\n this.decays = this._decaysCopy;\r\n this.setStandardDecays();\r\n }\r\n\r\n dfsSmallInitialization(vertices) {\r\n for (let i = 0; i < vertices.length; ++i) {\r\n this.vertices[vertices[i]].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n smallBlockDfsStart(edge) {\r\n let stackVisitedVertexes = [];\r\n let depth = this.smallDfs(this.vertices[edge.sourceId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n stackVisitedVertexes = [];\r\n depth = this.smallDfs(this.vertices[edge.targetId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n this._decaysCopy.push(edge.id);\r\n }\r\n }\r\n }\r\n\r\n smallDfs(vertex, depth, stackVisitedVertexes) {\r\n stackVisitedVertexes.push(vertex.id);\r\n if (depth > 3) {\r\n return depth;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return depth;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n ++depth;\r\n\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n depth = this.smallDfs(this.vertices[nextVertex], depth, stackVisitedVertexes);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n return depth;\r\n }\r\n\r\n setStandardDecays() {\r\n this.edges.forEach(e => {\r\n e.setDecay(false);\r\n });\r\n this.decays.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n });\r\n }\r\n\r\n standardDecays() {\r\n for (let i = 0; i < this.edges.length; i++) {\r\n if (this.edges[i].bondType === '=') {\r\n let dec = this.isDecayPoint(this.edges[i].sourceId, this.edges[i].targetId, i);\r\n if (dec !== false) {\r\n this.edges[dec].setDecay(true);\r\n this.decays.push(dec);\r\n this.edges[dec].setDecayAll(true);\r\n this.decaysAll.push(dec);\r\n }\r\n }\r\n }\r\n this.reduceDecays();\r\n }\r\n\r\n sourceDecays() {\r\n this.options.decaySource.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n this.edges[e].setDecayAll(true);\r\n this.decays.push(e);\r\n this.decaysAll.push(e);\r\n });\r\n }\r\n\r\n /**\r\n * check if its decay point of specific decay types\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @param decayTypes DecayPoint\r\n * @returns {int|boolean} return edge id when found, otherwise return false\r\n */\r\n isDecayPoint(sourceId, targetId, edgeBondId, decayTypes = DecayPoint.VALUES.ALL) {\r\n switch (decayTypes) {\r\n case DecayPoint.VALUES.ALL:\r\n let found = this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n if (found === false) {\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n } else {\r\n return found;\r\n }\r\n case DecayPoint.VALUES.COO:\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n case DecayPoint.VALUES.CONH:\r\n return this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-O- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'O', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'O', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-NH- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'N', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'N', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay point edge id of right neighbour\r\n * @param vertexId\r\n * @param element\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayId(vertexId, element, edgeBondId) {\r\n for (let i = 0; i < this.vertices[vertexId].edges.length; i++) {\r\n let edgeId = this.checkNeighbourEdgeId(this.vertices[vertexId].edges[i], vertexId, element);\r\n if (edgeId !== false && edgeId !== edgeBondId) {\r\n return edgeId;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find edge id of decay point\r\n * @param edgeId\r\n * @param vertexId\r\n * @param element\r\n * @returns {int|boolean}\r\n */\r\n checkNeighbourEdgeId(edgeId, vertexId, element) {\r\n if ((this.edges[edgeId].sourceId === vertexId && this.vertices[this.edges[edgeId].targetId].value.element === element) ||\r\n (this.edges[edgeId].targetId === vertexId && this.vertices[this.edges[edgeId].sourceId].value.element === element)) {\r\n return edgeId;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clears all the elements in this graph (edges and vertices).\r\n */\r\n clear() {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.vertexIdsToEdgeId = {};\r\n }\r\n\r\n /**\r\n * Add a vertex to the graph.\r\n *\r\n * @param {Vertex} vertex A new vertex.\r\n * @returns {Number} The vertex id of the new vertex.\r\n */\r\n addVertex(vertex) {\r\n vertex.id = this.vertices.length;\r\n this.vertices.push(vertex);\r\n\r\n return vertex.id;\r\n }\r\n\r\n /**\r\n * Add an edge to the graph.\r\n *\r\n * @param {Edge} edge A new edge.\r\n * @returns {Number} The edge id of the new edge.\r\n */\r\n addEdge(edge) {\r\n let source = this.vertices[edge.sourceId];\r\n let target = this.vertices[edge.targetId];\r\n\r\n edge.id = this.edges.length;\r\n this.edges.push(edge);\r\n\r\n this.vertexIdsToEdgeId[edge.sourceId + '_' + edge.targetId] = edge.id;\r\n this.vertexIdsToEdgeId[edge.targetId + '_' + edge.sourceId] = edge.id;\r\n edge.isPartOfAromaticRing = source.value.isPartOfAromaticRing && target.value.isPartOfAromaticRing;\r\n\r\n source.value.bondCount += edge.weight;\r\n target.value.bondCount += edge.weight;\r\n\r\n source.edges.push(edge.id);\r\n target.edges.push(edge.id);\r\n\r\n return edge.id;\r\n }\r\n\r\n /**\r\n * Returns the edge between two given vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {(Edge|null)} The edge or, if no edge can be found, null.\r\n */\r\n getEdge(vertexIdA, vertexIdB) {\r\n let edgeId = this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB];\r\n\r\n return edgeId === undefined ? null : this.edges[edgeId];\r\n }\r\n\r\n /**\r\n * Returns the ids of edges connected to a vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Number[]} An array containing the ids of edges connected to the vertex.\r\n */\r\n getEdges(vertexId) {\r\n let edgeIds = Array();\r\n let vertex = this.vertices[vertexId];\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n edgeIds.push(this.vertexIdsToEdgeId[vertexId + '_' + vertex.neighbours[i]]);\r\n }\r\n\r\n return edgeIds;\r\n }\r\n\r\n\r\n /**\r\n * Check whether or not two vertices are connected by an edge.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not two vertices are connected by an edge.\r\n */\r\n hasEdge(vertexIdA, vertexIdB) {\r\n return this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB] !== undefined\r\n }\r\n\r\n /**\r\n * Returns an array containing the vertex ids of this graph.\r\n *\r\n * @returns {Number[]} An array containing all vertex ids of this graph.\r\n */\r\n getVertexList() {\r\n let arr = [this.vertices.length];\r\n\r\n for (var i = 0; i < this.vertices.length; i++) {\r\n arr[i] = this.vertices[i].id;\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array containing source, target arrays of this graphs edges.\r\n *\r\n * @returns {Array[]} An array containing source, target arrays of this graphs edges. Example: [ [ 2, 5 ], [ 6, 9 ] ].\r\n */\r\n getEdgeList() {\r\n let arr = Array(this.edges.length);\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n arr[i] = [this.edges[i].sourceId, this.edges[i].targetId];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph.\r\n */\r\n getAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph with all bridges removed (thus the components). Thus the remaining vertices are all part of ring systems.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph with all bridges removed.\r\n */\r\n getComponentsAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n let bridges = this.getBridges();\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n for (var i = 0; i < bridges.length; i++) {\r\n adjacencyMatrix[bridges[i][0]][bridges[i][1]] = 0;\r\n adjacencyMatrix[bridges[i][1]][bridges[i][0]] = 0;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency matrix of the subgraph.\r\n */\r\n getSubgraphAdjacencyMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyMatrix[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of the graph.\r\n *\r\n * @returns {Array[]} The distance matrix of the graph.\r\n */\r\n getDistanceMatrix() {\r\n let length = this.vertices.length;\r\n let adja = this.getAdjacencyMatrix();\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The distance matrix of the subgraph.\r\n */\r\n getSubgraphDistanceMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adja = this.getSubgraphAdjacencyMatrix(vertexIds);\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of the graph.\r\n *\r\n * @returns {Array[]} The adjancency list of the graph.\r\n */\r\n getAdjacencyList() {\r\n let length = this.vertices.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = [];\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(this.vertices[i].id, this.vertices[j].id)) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency list of the subgraph.\r\n */\r\n getSubgraphAdjacencyList(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = Array();\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Returns an array containing the edge ids of bridges. A bridge splits the graph into multiple components when removed.\r\n *\r\n * @returns {Number[]} An array containing the edge ids of the bridges.\r\n */\r\n getBridges() {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n let disc = new Array(length);\r\n let low = new Array(length);\r\n let parent = new Array(length);\r\n let adj = this.getAdjacencyList();\r\n let outBridges = Array();\r\n\r\n visited.fill(false);\r\n parent.fill(null);\r\n this._time = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (!visited[i]) {\r\n this._bridgeDfs(i, visited, disc, low, parent, adj, outBridges);\r\n }\r\n }\r\n\r\n return outBridges;\r\n }\r\n\r\n /**\r\n * Traverses the graph in breadth-first order.\r\n *\r\n * @param {Number} startVertexId The id of the starting vertex.\r\n * @param {Function} callback The callback function to be called on every vertex.\r\n */\r\n traverseBF(startVertexId, callback) {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n\r\n visited.fill(false);\r\n\r\n var queue = [startVertexId];\r\n\r\n while (queue.length > 0) {\r\n // JavaScripts shift() is O(n) ... bad JavaScript, bad!\r\n let u = queue.shift();\r\n let vertex = this.vertices[u];\r\n\r\n callback(vertex);\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n let v = vertex.neighbours[i];\r\n if (!visited[v]) {\r\n visited[v] = true;\r\n queue.push(v);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the depth of a subtree in the direction opposite to the vertex specified as the parent vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId The id of a neighbouring vertex.\r\n * @returns {Number} The depth of the sub-tree.\r\n */\r\n getTreeDepth(vertexId, parentVertexId) {\r\n if (vertexId === null || parentVertexId === null) {\r\n return 0;\r\n }\r\n\r\n let neighbours = this.vertices[vertexId].getSpanningTreeNeighbours(parentVertexId);\r\n let max = 0;\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n let childId = neighbours[i];\r\n let d = this.getTreeDepth(childId, vertexId);\r\n\r\n if (d > max) {\r\n max = d;\r\n }\r\n }\r\n\r\n return max + 1;\r\n }\r\n\r\n /**\r\n * Traverse a sub-tree in the graph.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId A neighbouring vertex.\r\n * @param {Function} callback The callback function that is called with each visited as an argument.\r\n * @param {Number} [maxDepth=999999] The maximum depth of the recursion.\r\n * @param {Boolean} [ignoreFirst=false] Whether or not to ignore the starting vertex supplied as vertexId in the callback.\r\n * @param {Number} [depth=1] The current depth in the tree.\r\n * @param {Uint8Array} [visited=null] An array holding a flag on whether or not a node has been visited.\r\n */\r\n traverseTree(vertexId, parentVertexId, callback, maxDepth = 999999, ignoreFirst = false, depth = 1, visited = null) {\r\n if (visited === null) {\r\n visited = new Uint8Array(this.vertices.length);\r\n }\r\n\r\n if (depth > maxDepth + 1 || visited[vertexId] === 1) {\r\n return;\r\n }\r\n\r\n visited[vertexId] = 1;\r\n\r\n let vertex = this.vertices[vertexId];\r\n let neighbours = vertex.getNeighbours(parentVertexId);\r\n\r\n if (!ignoreFirst || depth > 1) {\r\n callback(vertex);\r\n }\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n this.traverseTree(neighbours[i], vertexId, callback, maxDepth, ignoreFirst, depth + 1, visited);\r\n }\r\n }\r\n\r\n /**\r\n * Positiones the (sub)graph using Kamada and Kawais algorithm for drawing general undirected graphs. https://pdfs.semanticscholar.org/b8d3/bca50ccc573c5cb99f7d201e8acce6618f04.pdf\r\n * There are undocumented layout parameters. They are undocumented for a reason, so be very careful.\r\n *\r\n * @param {Number[]} vertexIds An array containing vertexIds to be placed using the force based layout.\r\n * @param {Vector2} center The center of the layout.\r\n * @param {Number} startVertexId A vertex id. Should be the starting vertex - e.g. the first to be positioned and connected to a previously place vertex.\r\n * @param {Ring} ring The bridged ring associated with this force-based layout.\r\n */\r\n kkLayout(vertexIds, center, startVertexId, ring, bondLength,\r\n threshold = 0.1, innerThreshold = 0.1, maxIteration = 2000,\r\n maxInnerIteration = 50, maxEnergy = 1e9) {\r\n\r\n let edgeStrength = bondLength;\r\n\r\n // Add vertices that are directly connected to the ring\r\n var i = vertexIds.length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n var j = vertex.neighbours.length;\r\n }\r\n\r\n let matDist = this.getSubgraphDistanceMatrix(vertexIds);\r\n let length = vertexIds.length;\r\n\r\n // Initialize the positions. Place all vertices on a ring around the center\r\n let radius = MathHelper.polyCircumradius(500, length);\r\n let angle = MathHelper.centralAngle(length);\r\n let a = 0.0;\r\n let arrPositionX = new Float32Array(length);\r\n let arrPositionY = new Float32Array(length);\r\n let arrPositioned = Array(length);\r\n\r\n i = length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n if (!vertex.positioned) {\r\n arrPositionX[i] = center.x + Math.cos(a) * radius;\r\n arrPositionY[i] = center.y + Math.sin(a) * radius;\r\n } else {\r\n arrPositionX[i] = vertex.position.x;\r\n arrPositionY[i] = vertex.position.y;\r\n }\r\n arrPositioned[i] = vertex.positioned;\r\n a += angle;\r\n }\r\n\r\n // Create the matrix containing the lengths\r\n let matLength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matLength[i] = new Array(length);\r\n var j = length;\r\n while (j--) {\r\n matLength[i][j] = bondLength * matDist[i][j];\r\n }\r\n }\r\n\r\n // Create the matrix containing the spring strenghts\r\n let matStrength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matStrength[i] = Array(length);\r\n var j = length;\r\n while (j--) {\r\n matStrength[i][j] = edgeStrength * Math.pow(matDist[i][j], -2.0);\r\n }\r\n }\r\n\r\n // Create the matrix containing the energies\r\n let matEnergy = Array(length);\r\n let arrEnergySumX = new Float32Array(length);\r\n let arrEnergySumY = new Float32Array(length);\r\n i = length;\r\n while (i--) {\r\n matEnergy[i] = Array(length);\r\n }\r\n\r\n i = length;\r\n let ux, uy, dEx, dEy, vx, vy, denom;\r\n\r\n while (i--) {\r\n ux = arrPositionX[i];\r\n uy = arrPositionY[i];\r\n dEx = 0.0;\r\n dEy = 0.0;\r\n let j = length;\r\n while (j--) {\r\n if (i === j) {\r\n continue;\r\n }\r\n vx = arrPositionX[j];\r\n vy = arrPositionY[j];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n matEnergy[i][j] = [\r\n matStrength[i][j] * ((ux - vx) - matLength[i][j] * (ux - vx) * denom),\r\n matStrength[i][j] * ((uy - vy) - matLength[i][j] * (uy - vy) * denom)\r\n ];\r\n matEnergy[j][i] = matEnergy[i][j];\r\n dEx += matEnergy[i][j][0];\r\n dEy += matEnergy[i][j][1];\r\n }\r\n arrEnergySumX[i] = dEx;\r\n arrEnergySumY[i] = dEy;\r\n }\r\n\r\n // Utility functions, maybe inline them later\r\n let energy = function (index) {\r\n return [arrEnergySumX[index] * arrEnergySumX[index] + arrEnergySumY[index] * arrEnergySumY[index], arrEnergySumX[index], arrEnergySumY[index]];\r\n };\r\n\r\n let highestEnergy = function () {\r\n let maxEnergy = 0.0;\r\n let maxEnergyId = 0;\r\n let maxDEX = 0.0;\r\n let maxDEY = 0.0;\r\n\r\n i = length;\r\n while (i--) {\r\n let [delta, dEX, dEY] = energy(i);\r\n\r\n if (delta > maxEnergy && arrPositioned[i] === false) {\r\n maxEnergy = delta;\r\n maxEnergyId = i;\r\n maxDEX = dEX;\r\n maxDEY = dEY;\r\n }\r\n }\r\n\r\n return [maxEnergyId, maxEnergy, maxDEX, maxDEY];\r\n };\r\n\r\n let update = function (index, dEX, dEY) {\r\n let dxx = 0.0;\r\n let dyy = 0.0;\r\n let dxy = 0.0;\r\n let ux = arrPositionX[index];\r\n let uy = arrPositionY[index];\r\n let arrL = matLength[index];\r\n let arrK = matStrength[index];\r\n\r\n i = length;\r\n while (i--) {\r\n if (i === index) {\r\n continue;\r\n }\r\n\r\n let vx = arrPositionX[i];\r\n let vy = arrPositionY[i];\r\n let l = arrL[i];\r\n let k = arrK[i];\r\n let m = (ux - vx) * (ux - vx);\r\n let denom = 1.0 / Math.pow(m + (uy - vy) * (uy - vy), 1.5);\r\n\r\n dxx += k * (1 - l * (uy - vy) * (uy - vy) * denom);\r\n dyy += k * (1 - l * m * denom);\r\n dxy += k * (l * (ux - vx) * (uy - vy) * denom);\r\n }\r\n\r\n // Prevent division by zero\r\n if (dxx === 0) {\r\n dxx = 0.1;\r\n }\r\n\r\n if (dyy === 0) {\r\n dyy = 0.1;\r\n }\r\n\r\n if (dxy === 0) {\r\n dxy = 0.1;\r\n }\r\n\r\n let dy = (dEX / dxx + dEY / dxy);\r\n dy /= (dxy / dxx - dyy / dxy); // had to split this onto two lines because the syntax highlighter went crazy.\r\n let dx = -(dxy * dy + dEX) / dxx;\r\n\r\n arrPositionX[index] += dx;\r\n arrPositionY[index] += dy;\r\n\r\n // Update the energies\r\n let arrE = matEnergy[index];\r\n dEX = 0.0;\r\n dEY = 0.0;\r\n\r\n ux = arrPositionX[index];\r\n uy = arrPositionY[index];\r\n\r\n let vx, vy, prevEx, prevEy, denom;\r\n\r\n i = length;\r\n while (i--) {\r\n if (index === i) {\r\n continue;\r\n }\r\n vx = arrPositionX[i];\r\n vy = arrPositionY[i];\r\n // Store old energies\r\n prevEx = arrE[i][0];\r\n prevEy = arrE[i][1];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n dx = arrK[i] * ((ux - vx) - arrL[i] * (ux - vx) * denom);\r\n dy = arrK[i] * ((uy - vy) - arrL[i] * (uy - vy) * denom);\r\n\r\n arrE[i] = [dx, dy];\r\n dEX += dx;\r\n dEY += dy;\r\n arrEnergySumX[i] += dx - prevEx;\r\n arrEnergySumY[i] += dy - prevEy;\r\n }\r\n arrEnergySumX[index] = dEX;\r\n arrEnergySumY[index] = dEY;\r\n };\r\n\r\n // Setting up variables for the while loops\r\n let maxEnergyId = 0;\r\n let dEX = 0.0;\r\n let dEY = 0.0;\r\n let delta = 0.0;\r\n let iteration = 0;\r\n let innerIteration = 0;\r\n\r\n while (maxEnergy > threshold && maxIteration > iteration) {\r\n iteration++;\r\n [maxEnergyId, maxEnergy, dEX, dEY] = highestEnergy();\r\n delta = maxEnergy;\r\n innerIteration = 0;\r\n while (delta > innerThreshold && maxInnerIteration > innerIteration) {\r\n innerIteration++;\r\n update(maxEnergyId, dEX, dEY);\r\n [delta, dEX, dEY] = energy(maxEnergyId);\r\n }\r\n }\r\n\r\n i = length;\r\n while (i--) {\r\n let index = vertexIds[i];\r\n let vertex = this.vertices[index];\r\n vertex.position.x = arrPositionX[i];\r\n vertex.position.y = arrPositionY[i];\r\n vertex.positioned = true;\r\n vertex.forcePositioned = true;\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getBridges().\r\n */\r\n _bridgeDfs(u, visited, disc, low, parent, adj, outBridges) {\r\n visited[u] = true;\r\n disc[u] = low[u] = ++this._time;\r\n\r\n for (var i = 0; i < adj[u].length; i++) {\r\n let v = adj[u][i];\r\n\r\n if (!visited[v]) {\r\n parent[v] = u;\r\n\r\n this._bridgeDfs(v, visited, disc, low, parent, adj, outBridges);\r\n\r\n low[u] = Math.min(low[u], low[v]);\r\n\r\n // If low > disc, we have a bridge\r\n if (low[v] > disc[u]) {\r\n outBridges.push([u, v]);\r\n }\r\n } else if (v !== parent[u]) {\r\n low[u] = Math.min(low[u], disc[v]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the connected components of the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Set[]} Connected components as sets.\r\n */\r\n static getConnectedComponents(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let components = [];\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n let component = Array();\r\n visited[u] = true;\r\n component.push(u);\r\n count++;\r\n Graph._ccGetDfs(u, visited, adjacencyMatrix, component);\r\n if (component.length > 1) {\r\n components.push(component);\r\n }\r\n }\r\n }\r\n\r\n return components;\r\n }\r\n\r\n /**\r\n * Returns the number of connected components for the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of connected components of the supplied graph.\r\n */\r\n static getConnectedComponentCount(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n visited[u] = true;\r\n count++;\r\n Graph._ccCountDfs(u, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponentCount().\r\n */\r\n static _ccCountDfs(u, visited, adjacencyMatrix) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n Graph._ccCountDfs(v, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponents().\r\n */\r\n static _ccGetDfs(u, visited, adjacencyMatrix, component) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n component.push(v);\r\n Graph._ccGetDfs(v, visited, adjacencyMatrix, component);\r\n }\r\n }\r\n\r\n /**\r\n * Revert decay point value and update list of decay points\r\n * when edge isn't decay point -> change mark edge as decay point and add edge to decays list\r\n * when edge is decay point -> unmark edge as decay point and remove edgeId from list of decays\r\n * @param edgeId\r\n */\r\n revertEdgeDecayPoint(edgeId) {\r\n this.edges[edgeId].isDecay = !this.edges[edgeId].isDecay;\r\n this.edges[edgeId].isDecayAll = !this.edges[edgeId].isDecayAll;\r\n if (this.edges[edgeId].isDecay) {\r\n this.decays.push(edgeId);\r\n this.decaysAll.push(edgeId);\r\n } else {\r\n let index = this.decays.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decays.splice(index, 1);\r\n }\r\n index = this.decaysAll.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decaysAll.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.decays;\r\n }\r\n\r\n /**\r\n * Build block of SMILES based on decay points\r\n * DFS pass through graph\r\n * but the numbers are already setup in vertex.value.ringbonds array so no need to second pass of dfs\r\n */\r\n buildSmiles() {\r\n let smiles = [];\r\n this._polyketide = false;\r\n this.dfsSmilesInitialization();\r\n if (this.decays.length === 0) {\r\n this.startDfs(this.vertices[0], smiles);\r\n return {blockSmiles: smiles, sequence: '[0]', sequenceType: SequenceType.VALUES.OTHER, decays: this.decays, isPolyketide: this._polyketide};\r\n } else {\r\n this.dfsBuildSmilesStart(smiles);\r\n }\r\n this.dfsSmilesInitialization();\r\n this.dfsSmallStart();\r\n this._smallGraph.oneCyclic();\r\n this._smallGraph.dfsSequenceStart();\r\n\r\n let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence);\r\n\r\n return {\r\n blockSmiles: sequenceData.smiles,\r\n sequence: sequenceData.sequence,\r\n sequenceType: this._smallGraph.sequenceType + ((this._smallGraph.sequenceType === 'linear' || this._smallGraph.sequenceType === 'cyclic') && this._polyketide ? '-polyketide' : ''),\r\n decays: this.decays,\r\n isPolyketide: this._polyketide\r\n }\r\n }\r\n\r\n sortSequence(smiles, sequence) {\r\n let permutation = this.getSequencePermutation(sequence);\r\n let newSmiles = new Array(permutation.length).fill(null);\r\n for (let i = 0; i < permutation.length; ++i) {\r\n newSmiles[i] = smiles[permutation[i][0]];\r\n }\r\n\r\n let position = 0;\r\n let char = sequence.charAt(position);\r\n let newSequence = '';\r\n while (true) {\r\n switch (char) {\r\n case '0':\r\n case '1':\r\n case '2':\r\n case '3':\r\n case '4':\r\n case '5':\r\n case '6':\r\n case '7':\r\n case '8':\r\n case '9':\r\n let number = char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n while(!isNaN(char)) {\r\n number += char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n let j;\r\n for (j = 0; j < permutation.length; ++j) {\r\n if (permutation[j][0] === number) {\r\n newSequence += j;\r\n break;\r\n }\r\n }\r\n continue;\r\n default:\r\n newSequence += char;\r\n }\r\n\r\n ++position;\r\n if (position >= sequence.length) {\r\n break;\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n return {sequence: newSequence, smiles: newSmiles};\r\n }\r\n\r\n getSequencePermutation(sequence) {\r\n let re = /\\d+/g;\r\n let match = null;\r\n let permutation = [];\r\n while ((match = re.exec(sequence)) != null) {\r\n permutation.push(match);\r\n }\r\n return permutation;\r\n }\r\n\r\n dfsSmallStart() {\r\n this._smallGraph = new SmallGraph();\r\n for (let index = 0; index < this._startingVertexes.length; ++index) {\r\n this._smallGraph.addVertex(new Node(this._startingVertexes[index].component));\r\n this.first = this._startingVertexes[index];\r\n this.dfsSmall(this._startingVertexes[index], this._componentsIsPolyketide[index]);\r\n }\r\n }\r\n\r\n /**\r\n * Initialize graph for dfs\r\n * set for all vertices vertexState to NotFound\r\n */\r\n dfsSmilesInitialization() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n /**\r\n * Starting function for DFS\r\n * starts on decay points (on edge), so start on both side of edge\r\n * @param {Array} smiles output param, array of SMILES blocks (string)\r\n */\r\n dfsBuildSmilesStart(smiles) {\r\n this._cnt = 0;\r\n this._markComponent = false;\r\n this._startingVertexes = [];\r\n for (let i = 0; i < this.decays.length; ++i) {\r\n let edge = this.edges[this.decays[i]];\r\n this.markingComponents(this.startDfs(this.vertices[edge.sourceId], smiles));\r\n this.markingComponents(this.startDfs(this.vertices[edge.targetId], smiles));\r\n }\r\n }\r\n\r\n markingComponents(isPolyketyde) {\r\n if (this._markComponent) {\r\n this._cnt++;\r\n this._markComponent = false;\r\n this._componentsIsPolyketide.push(isPolyketyde);\r\n }\r\n }\r\n\r\n /**\r\n * Start DFS for build SMILES of blocks\r\n * @param {Vertex} vertex to start DFS\r\n * @param {Array} smiles output param, array od SMILES\r\n */\r\n startDfs(vertex, smiles) {\r\n let isPolyketide = new MutableBoolean(true);\r\n let decaysCounter = new MutableCounter();\r\n let vertexCounter = new MutableCounter();\r\n let through = [];\r\n let stackSmiles = [];\r\n this.first = vertex.id;\r\n this._isCyclic = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.dfsSmiles(vertex, stackSmiles, isPolyketide, decaysCounter, through, vertexCounter);\r\n if (decaysCounter.getValue() < 2 && isPolyketide.getValue() === true) {\r\n isPolyketide.setValue(through.every(vertex => vertex === 'O' || vertex === 'N') && vertexCounter.getValue() > 4);\r\n }\r\n if (this._isCyclic) {\r\n this.closedToNotFound();\r\n stackSmiles = [];\r\n this.dfsSmiles(vertex, stackSmiles, new MutableBoolean(true), new MutableCounter(), [], new MutableCounter(), -1, true);\r\n }\r\n this.closedToFullyClosed();\r\n\r\n stackSmiles = Graph.removeUnnecessaryParentheses(stackSmiles);\r\n let smile = Graph.removeUnnecessaryNumbers(stackSmiles.join(\"\"));\r\n if (smile.length !== 0) {\r\n smiles.push({smiles: smile, isPolyketide: isPolyketide.getValue()});\r\n if (isPolyketide.getValue() === true) {\r\n this._polyketide = true;\r\n }\r\n }\r\n return isPolyketide.getValue();\r\n }\r\n\r\n closedToNotFound() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n }\r\n\r\n closedToFullyClosed() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.FULLY_CLOSED;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * DFS for SMILES\r\n * @param {Vertex} vertex\r\n * @param {Array} stackSmiles output param\r\n * @param {MutableBoolean} isPolyketide\r\n * @param {MutableCounter} cntDecays\r\n * @param {Array} through\r\n * @param {MutableCounter} vertexCounter\r\n * @param lastVertexId last vertex id for setup digits\r\n * @param isSecondPass is second pass of dfs\r\n */\r\n dfsSmiles(vertex, stackSmiles, isPolyketide, cntDecays, through, vertexCounter, lastVertexId = -1, isSecondPass = false) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN && !isSecondPass && lastVertexId !== -1) {\r\n this._isCyclic = true;\r\n if (!vertex.digits.some(e => this.vertices[lastVertexId].digits.includes(e))) {\r\n vertex.digits.push(this._digitCounter);\r\n this.vertices[lastVertexId].digits.push(this._digitCounter);\r\n this._digitCounter++;\r\n }\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n if (vertex.value.element === 'H') {\r\n return;\r\n }\r\n\r\n if (this.first === vertex.id && vertex.value.element === \"C\" && isPolyketide.getValue()) {\r\n stackSmiles.push(\"O\");\r\n isPolyketide.setValue(false);\r\n }\r\n\r\n if (vertex.value.bracket) {\r\n stackSmiles.push(\"[\");\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n if (vertex.value.bracket.hcount > 0) {\r\n stackSmiles.push('H');\r\n if (vertex.value.bracket.hcount > 1) {\r\n stackSmiles.push(vertex.value.bracket.hcount);\r\n }\r\n }\r\n if (vertex.value.bracket.charge > 0) {\r\n stackSmiles.push('+');\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n } else if (vertex.value.bracket.charge < 0) {\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n }\r\n stackSmiles.push(\"]\");\r\n } else {\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n }\r\n vertexCounter.increment();\r\n\r\n if (isSecondPass) {\r\n stackSmiles.push(this.smilesNumbersAdd(vertex));\r\n }\r\n\r\n if (!this._markComponent) {\r\n this._startingVertexes.push(vertex);\r\n }\r\n vertex.component = this._cnt;\r\n this._markComponent = true;\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n if (edge.isDecayAll && lastVertexId !== nextVertex) {\r\n through.push(vertex.value.element);\r\n }\r\n if (edge.isDecay) {\r\n cntDecays.increment();\r\n if (vertex.value.element === \"C\" && vertex.id !== this.first && isPolyketide.getValue()) {\r\n stackSmiles.push(\"(\");\r\n stackSmiles.push(\"O\");\r\n stackSmiles.push(\")\");\r\n isPolyketide.setValue(false);\r\n }\r\n continue;\r\n }\r\n stackSmiles.push(\"(\");\r\n Graph.addBondTypeToStack(edge, stackSmiles);\r\n if (lastVertexId !== nextVertex) {\r\n this.dfsSmiles(this.vertices[nextVertex], stackSmiles, isPolyketide, cntDecays, through, vertexCounter, vertex.id, isSecondPass);\r\n }\r\n Graph.checkStack(stackSmiles);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSmall(vertex, isPolyketide) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n\r\n this._smallGraph.addNeighbour(vertex.component, this.vertices[Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId)].component, Direction.getProperValue(isPolyketide, vertex.value.element, vertex.id, this.first));\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n this.dfsSmall(this.vertices[nextVertex], isPolyketide);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n\r\n static printVertexValue(stackSmiles, vertex) {\r\n if (vertex.value.isPartOfAromaticRing) {\r\n stackSmiles.push(vertex.value.element.toLowerCase());\r\n } else {\r\n stackSmiles.push(vertex.value.element);\r\n }\r\n }\r\n\r\n /**\r\n * Remove numbers which is neighbours in SMILES notation -> need to perform in cyclic structures\r\n * @param {String} smiles SMILES\r\n * @return {String} repaired SMILES\r\n */\r\n static removeUnnecessaryNumbers(smiles) {\r\n if (smiles === null) {\r\n return '';\r\n }\r\n try {\r\n let numbers = this.getNumbers(smiles);\r\n for (let number of numbers) {\r\n let first = this.findFirst(smiles, number);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n let tmpRange = this.removeRangeLast(smiles, first, second, number);\r\n smiles = this.repairSmiles(smiles, tmpRange, first, second, number);\r\n }\r\n return smiles;\r\n } catch (ex) {\r\n return smiles;\r\n }\r\n }\r\n\r\n /**\r\n * Remove unnecessary numbers from SMILES\r\n * @param {String} smiles\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {*}\r\n */\r\n static removeNumbers(smiles, first, second, number) {\r\n if (number > 9) {\r\n let numLength = number.toString().length;\r\n smiles = smiles.slice(0, first - 1) + smiles.slice(first + numLength);\r\n return smiles.slice(0, second - 2 - numLength) + smiles.slice(second - 1);\r\n } else {\r\n smiles = smiles.slice(0, first) + smiles.slice(first + 1);\r\n return smiles.slice(0, second - 1) + smiles.slice(second);\r\n }\r\n }\r\n\r\n /**\r\n * Reapair SMILES\r\n * @param {String} smiles\r\n * @param {String} tmpRange\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {String|*}\r\n */\r\n static repairSmiles(smiles, tmpRange, first, second, number) {\r\n let pattern = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])$\");\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let patternOrg = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])\");\r\n if (patternOrg.test(tmpRange)) {\r\n return smiles;\r\n }\r\n\r\n while (tmpRange.length !== 0) {\r\n if (tmpRange[0] === '(') {\r\n tmpRange = tmpRange.substring(1);\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let leftBrackets = 1;\r\n let rightBrackets = 0;\r\n while (leftBrackets !== rightBrackets) {\r\n switch (tmpRange[0]) {\r\n case '(':\r\n leftBrackets++;\r\n break;\r\n case ')':\r\n rightBrackets++;\r\n break;\r\n }\r\n if (\"\" === tmpRange) {\r\n return smiles;\r\n }\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n return this.repairSmiles(smiles, tmpRange, first, second, number);\r\n } else {\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Substring in range and remove last Organic Subset\r\n * @param smiles\r\n * @param first\r\n * @param second\r\n * @param number\r\n * @return {string}\r\n */\r\n static removeRangeLast(smiles, first, second, number) {\r\n if (number > 9) {\r\n return smiles.substring(first + number.toString().length, second - 1);\r\n } else {\r\n return smiles.substring(first + 1, second);\r\n }\r\n }\r\n\r\n /**\r\n * Get numbers from SMILES\r\n * @param smiles\r\n * @return {Set}\r\n */\r\n static getNumbers(smiles) {\r\n let numbers = new Set();\r\n for (let index = 0; index < smiles.length; ++index) {\r\n if (!isNaN(smiles[index])) {\r\n numbers.add(smiles[index]);\r\n } else if (smiles[index] === '%') {\r\n index++;\r\n let num = \"\";\r\n while (!isNaN(smiles[index])) {\r\n num += smiles[index];\r\n index++;\r\n if (index >= smiles.length) {\r\n break;\r\n }\r\n }\r\n index--;\r\n numbers.add(num);\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * return index of first occurrence number\r\n * @param smiles\r\n * @param number\r\n * @return {number}\r\n */\r\n static findFirst(smiles, number) {\r\n return smiles.indexOf(number);\r\n }\r\n\r\n /**\r\n * return index of first occurrence number from index + 1\r\n * @param smiles\r\n * @param from range no including this point (from, Infinity) = [from + 1, Infinity)\r\n * @param number\r\n * @return {*}\r\n */\r\n static findSecond(smiles, from, number) {\r\n let result = smiles.indexOf(number, from);\r\n if (result === -1) {\r\n throw \"Not Found\";\r\n }\r\n return result;\r\n }\r\n\r\n\r\n smilesNumbersAdd(vertex) {\r\n let numbers = '';\r\n for (let i = 0; i < vertex.digits.length; ++i) {\r\n let num = vertex.digits[i];\r\n if (this._printedDigits.some(e => e === num)) {\r\n let nextVertex = this.vertices.find(e => e.digits.includes(num) && e.id !== vertex.id);\r\n let intersection = vertex.edges.filter(element => nextVertex.edges.includes(element));\r\n\r\n if (intersection.length > 0) {\r\n let bond = this.edges[intersection[0]].bondType;\r\n if (bond !== '-') {\r\n numbers += bond;\r\n }\r\n }\r\n }\r\n\r\n this._printedDigits.push(num);\r\n let numString = num.toString();\r\n if (numString.length === 1) {\r\n numbers += numString;\r\n } else {\r\n numbers += '%' + numString;\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * Return other vertex id then the actual vertex id\r\n * when vertexId === sourceId return targetId\r\n * when vertexId === targetId return sourceId\r\n * @param {Number} vertexId actual vertex id\r\n * @param {Number} sourceId source vertex id\r\n * @param {Number} targetId target vertex id\r\n * @return {Number}\r\n */\r\n static getProperVertex(vertexId, sourceId, targetId) {\r\n if (vertexId === sourceId) return targetId;\r\n else return sourceId;\r\n }\r\n\r\n static repairNumbers(smiles) {\r\n try {\r\n let numbers = Array.from(this.getNumbers(smiles));\r\n numbers.sort(function (a, b) {\r\n return b - a\r\n });\r\n\r\n let index = 1;\r\n for (let number of numbers) {\r\n if (index === number) {\r\n continue;\r\n }\r\n let first = this.findFirst(smiles, number);\r\n if (number > 9) {\r\n smiles = smiles.slice(0, first - 1) + index + smiles.slice(first + number.toString().length);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second - 1) + index + smiles.slice(second + number.toString().length);\r\n } else {\r\n smiles = smiles.slice(0, first) + index + smiles.slice(first + 1);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second) + index + smiles.slice(second + 1);\r\n }\r\n index++;\r\n }\r\n } catch (e) {\r\n return smiles;\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from SMILES\r\n * example CCC(CC)(C) -> CCC(CC)C\r\n * example C(=O)C(C(C)) -> C(=O)CCC\r\n * @param {Array} stackRight\r\n * @return {Array}\r\n */\r\n static removeUnnecessaryParentheses(stackRight) {\r\n if (stackRight.length === 0) return [];\r\n let stackLeft = [], lastLiteral = \"\", literal = \"\";\r\n while (stackRight.length > 0) {\r\n literal = stackRight.shift();\r\n if ((\")\".localeCompare(literal) === 0 && \")\".localeCompare(lastLiteral) === 0)) {\r\n Graph.removeParentheses(stackLeft, false, literal);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n lastLiteral = literal;\r\n }\r\n\r\n literal = stackLeft.pop();\r\n if ((\")\".localeCompare(literal) === 0 && stackRight.length === 0)) {\r\n Graph.removeParentheses(stackLeft);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n return stackLeft;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from stack\r\n * go through stack and when find proper closing bracket,\r\n * then remove it and push back removed data when searching in stack\r\n * @param {Array} stack with unnecessary parentheses to remove\r\n * @param {Boolean} end treat with situation when \")\" is last character of stack -> end = true, else where end = false\r\n * @param {String} literal, when end = false, need to pop from stack and at the end add literal back to stack\r\n */\r\n static removeParentheses(stack, end = true, literal = \"\") {\r\n let stackTmp = [];\r\n let leftBraces = 0, rightBraces = 1;\r\n if (!end) {\r\n stack.pop();\r\n }\r\n while (true) {\r\n let lit = stack.pop();\r\n if (\"(\".localeCompare(lit) === 0) {\r\n leftBraces++;\r\n } else if (\")\".localeCompare(lit) === 0) {\r\n rightBraces++;\r\n }\r\n if (leftBraces === rightBraces) {\r\n Graph.moveAllValuesInStackToAnotherStack(stackTmp, stack);\r\n if (!end) {\r\n stack.push(literal);\r\n }\r\n break;\r\n }\r\n stackTmp.push(lit);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all values from stackSource and push it to stackDestination\r\n * @param {Array} stackSource stack to remove values\r\n * @param {Array} stackDestination stack to add values from stackSource\r\n */\r\n static moveAllValuesInStackToAnotherStack(stackSource, stackDestination) {\r\n while (stackSource.length > 0) {\r\n stackDestination.push(stackSource.pop());\r\n }\r\n }\r\n\r\n /**\r\n * Check last value of stack\r\n * if it one of (, -, = or # then remove all characters in stack to first ( from the end of stack\r\n * elsewhere add ) to stack\r\n * @param {Array} stackSmiles\r\n */\r\n static checkStack(stackSmiles) {\r\n switch (stackSmiles[stackSmiles.length - 1]) {\r\n case \"(\":\r\n case \"-\":\r\n case \"=\":\r\n case \"#\":\r\n Graph.removeAllFromStackToFirstLeftBrace(stackSmiles);\r\n break;\r\n default:\r\n stackSmiles.push(\")\");\r\n }\r\n }\r\n\r\n /**\r\n * Remove all characters from stack to first \"(\"\r\n * @param {Array} stackSmiles\r\n */\r\n static removeAllFromStackToFirstLeftBrace(stackSmiles) {\r\n let literal = stackSmiles.pop();\r\n while (literal !== \"(\") {\r\n if (stackSmiles.length === 0) break;\r\n literal = stackSmiles.pop();\r\n }\r\n }\r\n\r\n /**\r\n * Add bond type to stack\r\n * if edge have = or # bond type add it to stack\r\n * @param {Edge} edge\r\n * @param {Array} stackSmiles\r\n */\r\n static addBondTypeToStack(edge, stackSmiles) {\r\n if (edge.bondType === \"=\" || edge.bondType === \"#\") {\r\n stackSmiles.push(edge.bondType);\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Graph;\r\n","//@ts-check\r\nconst Vector2 = require('./Vector2')\r\n\r\n/** \r\n * A class representing a line.\r\n * \r\n * @property {Vector2} from The Vector2 defining the start of the line.\r\n * @property {Vector2} to The Vector2 defining the end of the line.\r\n * @property {String} elementFrom The element symbol associated with the start of the line.\r\n * @property {String} elementTo The element symbol associated with the end of the line.\r\n * @property {Boolean} chiralFrom A boolean indicating whether or not the source atom is a chiral center.\r\n * @property {Boolean} chiralTo A boolean indicating whether or tno the target atom is a chiral center.\r\n */\r\nclass Line {\r\n /**\r\n * The constructor for the class Line.\r\n *\r\n * @param {Vector2} [from=new Vector2(0, 0)] A vector marking the beginning of the line.\r\n * @param {Vector2} [to=new Vector2(0, 0)] A vector marking the end of the line.\r\n * @param {string} [elementFrom=null] A one-letter representation of the element associated with the vector marking the beginning of the line.\r\n * @param {string} [elementTo=null] A one-letter representation of the element associated with the vector marking the end of the line.\r\n * @param {Boolean} [chiralFrom=false] Whether or not the from atom is a chiral center.\r\n * @param {Boolean} [chiralTo=false] Whether or not the to atom is a chiral center.\r\n * @param {Boolean} [isDecayPoint=false] Whether or not the edge is a decay point\r\n */\r\n constructor(from = new Vector2(0,0), to = new Vector2(0, 0), elementFrom = null, elementTo = null, chiralFrom = false, chiralTo = false, isDecayPoint = false) {\r\n this.from = from;\r\n this.to = to;\r\n this.elementFrom = elementFrom;\r\n this.elementTo = elementTo;\r\n this.chiralFrom = chiralFrom;\r\n this.chiralTo = chiralTo;\r\n this.isDecayPoint = isDecayPoint;\r\n }\r\n\r\n /**\r\n * Clones this line and returns the clone.\r\n *\r\n * @returns {Line} A clone of this line.\r\n */\r\n clone() {\r\n return new Line(this.from.clone(), this.to.clone(), this.elementFrom, this.elementTo);\r\n }\r\n\r\n /**\r\n * Returns the length of this line.\r\n *\r\n * @returns {Number} The length of this line.\r\n */\r\n getLength() {\r\n return Math.sqrt(Math.pow(this.to.x - this.from.x, 2) + \r\n Math.pow(this.to.y - this.from.y, 2));\r\n }\r\n\r\n\r\n /**\r\n * Returns the angle of the line in relation to the coordinate system (the x-axis).\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n // Get the angle between the line and the x-axis\r\n let diff = Vector2.subtract(this.getRightVector(), this.getLeftVector());\r\n return diff.angle();\r\n }\r\n\r\n /**\r\n * Returns the right vector (the vector with the larger x value).\r\n *\r\n * @returns {Vector2} The right vector.\r\n */\r\n getRightVector() {\r\n // Return the vector with the larger x value (the right one)\r\n if (this.from.x < this.to.x) {\r\n return this.to;\r\n } else {\r\n return this.from;\r\n }\r\n }\r\n \r\n /**\r\n * Returns the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {Vector2} The left vector.\r\n */\r\n getLeftVector() {\r\n // Return the vector with the smaller x value (the left one)\r\n if (this.from.x < this.to.x) {\r\n return this.from;\r\n } else {\r\n return this.to;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the right vector (the vector with the larger x value).\r\n *\r\n * @returns {String} The element associated with the right vector.\r\n */\r\n getRightElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementTo;\r\n } else {\r\n return this.elementFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {String} The element associated with the left vector.\r\n */\r\n getLeftElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementFrom;\r\n } else {\r\n return this.elementTo;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the right vector (the vector with the larger x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the right vector is a chiral center.\r\n */\r\n getRightChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralTo;\r\n } else {\r\n return this.chiralFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the left vector (the vector with the smaller x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the left vector is a chiral center.\r\n */\r\n getLeftChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralFrom;\r\n } else {\r\n return this.chiralTo;\r\n }\r\n }\r\n\r\n /**\r\n * Set the value of the right vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setRightVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.to.x = x;\r\n this.to.y = y;\r\n } else {\r\n this.from.x = x;\r\n this.from.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Set the value of the left vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setLeftVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.from.x = x;\r\n this.from.y = y;\r\n } else {\r\n this.to.x = x;\r\n this.to.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this line to be aligned with the x-axis. The center of rotation is the left vector.\r\n *\r\n * @returns {Line} This line.\r\n */\r\n rotateToXAxis() {\r\n let left = this.getLeftVector();\r\n \r\n this.setRightVector(left.x + this.getLength(), left.y);\r\n \r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate the line by a given value (in radians). The center of rotation is the left vector.\r\n *\r\n * @param {Number} theta The angle (in radians) to rotate the line.\r\n * @returns {Line} This line.\r\n */\r\n rotate(theta) {\r\n let l = this.getLeftVector();\r\n let r = this.getRightVector();\r\n let sinTheta = Math.sin(theta);\r\n let cosTheta = Math.cos(theta);\r\n\r\n let x = cosTheta * (r.x - l.x) - sinTheta * (r.y - l.y) + l.x;\r\n let y = sinTheta * (r.x - l.x) - cosTheta * (r.y - l.y) + l.y;\r\n \r\n this.setRightVector(x, y);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"from\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenFrom(by) {\r\n let f = Vector2.subtract(this.to, this.from);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.from.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"to\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenTo(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.to.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shorten the right side.\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenRight(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenTo(by);\r\n } else {\r\n this.shortenFrom(by);\r\n }\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Shorten the left side.\r\n * \r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenLeft(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenFrom(by);\r\n } else {\r\n this.shortenTo(by);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from both directions by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shorten(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by / 2.0);\r\n \r\n this.to.add(f);\r\n this.from.subtract(f);\r\n\r\n return this;\r\n }\r\n}\r\n\r\nmodule.exports = Line;","/** \r\n * A static class containing helper functions for math-related tasks. \r\n */\r\nclass MathHelper {\r\n /**\r\n * Rounds a value to a given number of decimals.\r\n *\r\n * @static\r\n * @param {Number} value A number.\r\n * @param {Number} decimals The number of decimals.\r\n * @returns {Number} A number rounded to a given number of decimals.\r\n */\r\n static round(value, decimals) {\r\n decimals = decimals ? decimals : 1;\r\n return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);\r\n }\r\n\r\n /**\r\n * Returns the means of the angles contained in an array. In radians.\r\n *\r\n * @static\r\n * @param {Number[]} arr An array containing angles (in radians).\r\n * @returns {Number} The mean angle in radians.\r\n */\r\n static meanAngle(arr) {\r\n let sin = 0.0;\r\n let cos = 0.0;\r\n \r\n for (var i = 0; i < arr.length; i++) {\r\n sin += Math.sin(arr[i]);\r\n cos += Math.cos(arr[i]);\r\n }\r\n\r\n return Math.atan2(sin / arr.length, cos / arr.length);\r\n }\r\n\r\n /**\r\n * Returns the inner angle of a n-sided regular polygon.\r\n *\r\n * @static\r\n * @param {Number} n Number of sides of a regular polygon.\r\n * @returns {Number} The inner angle of a given regular polygon.\r\n */\r\n static innerAngle(n) {\r\n return MathHelper.toRad((n - 2) * 180 / n);\r\n }\r\n\r\n /**\r\n * Returns the circumradius of a n-sided regular polygon with a given side-length.\r\n *\r\n * @static\r\n * @param {Number} s The side length of the regular polygon.\r\n * @param {Number} n The number of sides.\r\n * @returns {Number} The circumradius of the regular polygon.\r\n */\r\n static polyCircumradius(s, n) {\r\n return s / (2 * Math.sin(Math.PI / n));\r\n }\r\n\r\n /**\r\n * Returns the apothem of a regular n-sided polygon based on its radius.\r\n *\r\n * @static\r\n * @param {Number} r The radius.\r\n * @param {Number} n The number of edges of the regular polygon.\r\n * @returns {Number} The apothem of a n-sided polygon based on its radius.\r\n */\r\n static apothem(r, n) {\r\n return r * Math.cos(Math.PI / n);\r\n }\r\n\r\n static apothemFromSideLength(s, n) {\r\n let r = MathHelper.polyCircumradius(s, n);\r\n \r\n return MathHelper.apothem(r, n);\r\n }\r\n\r\n /**\r\n * The central angle of a n-sided regular polygon. In radians.\r\n *\r\n * @static\r\n * @param {Number} n The number of sides of the regular polygon.\r\n * @returns {Number} The central angle of the n-sided polygon in radians.\r\n */\r\n static centralAngle(n) {\r\n return MathHelper.toRad(360 / n);\r\n }\r\n\r\n /**\r\n * Convertes radians to degrees.\r\n *\r\n * @static\r\n * @param {Number} rad An angle in radians.\r\n * @returns {Number} The angle in degrees.\r\n */\r\n static toDeg(rad) {\r\n return rad * MathHelper.degFactor;\r\n }\r\n\r\n /**\r\n * Converts degrees to radians.\r\n *\r\n * @static\r\n * @param {Number} deg An angle in degrees.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static toRad(deg) {\r\n return deg * MathHelper.radFactor;\r\n }\r\n\r\n /**\r\n * Returns the parity of the permutation (1 or -1)\r\n * @param {(Array|Uint8Array)} arr An array containing the permutation.\r\n * @returns {Number} The parity of the permutation (1 or -1), where 1 means even and -1 means odd.\r\n */\r\n static parityOfPermutation(arr) {\r\n let visited = new Uint8Array(arr.length);\r\n let evenLengthCycleCount = 0;\r\n\r\n let traverseCycle = function(i, cycleLength = 0) {\r\n if (visited[i] === 1) {\r\n return cycleLength;\r\n }\r\n\r\n cycleLength++;\r\n\r\n visited[i] = 1;\r\n return traverseCycle(arr[i], cycleLength);\r\n }\r\n\r\n for (var i = 0; i < arr.length; i++) {\r\n if (visited[i] === 1) {\r\n continue;\r\n }\r\n\r\n let cycleLength = traverseCycle(i);\r\n evenLengthCycleCount += (1 - cycleLength % 2);\r\n }\r\n\r\n return evenLengthCycleCount % 2 ? -1 : 1;\r\n }\r\n\r\n /** The factor to convert degrees to radians. */\r\n static get radFactor() {\r\n return Math.PI / 180.0;\r\n }\r\n\r\n /** The factor to convert radians to degrees. */\r\n static get degFactor() {\r\n return 180.0 / Math.PI;\r\n }\r\n\r\n /** Two times PI. */\r\n static get twoPI() {\r\n return 2.0 * Math.PI;\r\n }\r\n}\r\n\r\nmodule.exports = MathHelper;","/**\r\n *@property {boolean} value is boolean\r\n */\r\nclass MutableBoolean {\r\n\r\n /**\r\n * @param {boolean} value\r\n */\r\n constructor(value) {\r\n this.value = value;\r\n }\r\n\r\n setValue(value) {\r\n this.value = value;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableBoolean;\r\n","/**\r\n * @param {Number} value\r\n */\r\nclass MutableCounter {\r\n\r\n constructor() {\r\n this.value = 0;\r\n }\r\n\r\n increment() {\r\n this.value++;\r\n }\r\n\r\n reset() {\r\n this.value = 0;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableCounter;\r\n","\r\nclass Neighbour {\r\n\r\n constructor(neighbour, direction) {\r\n this.neighbour = neighbour;\r\n this.direction = direction;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Neighbour;\r\n","//@ts-check\r\nconst VertexState = require(\"./VertexState\");\r\n\r\nclass Node {\r\n\r\n constructor(id) {\r\n this.id = id;\r\n this.neighbours = [];\r\n this.onRing = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n\r\n addNeighbour(neighbour) {\r\n this.neighbours.push(neighbour);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Node;\r\n","// WHEN REPLACING, CHECK FOR:\r\n// KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\nmodule.exports = (function () {\r\n \"use strict\";\r\n\r\n /*\r\n * Generated by PEG.js 0.10.0.\r\n *\r\n * http://pegjs.org/\r\n */\r\n\r\n function peg$subclass(child, parent) {\r\n function ctor() {\r\n this.constructor = child;\r\n }\r\n ctor.prototype = parent.prototype;\r\n child.prototype = new ctor();\r\n }\r\n\r\n function peg$SyntaxError(message, expected, found, location) {\r\n this.message = message;\r\n this.expected = expected;\r\n this.found = found;\r\n this.location = location;\r\n this.name = \"SyntaxError\";\r\n\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(this, peg$SyntaxError);\r\n }\r\n }\r\n\r\n peg$subclass(peg$SyntaxError, Error);\r\n\r\n peg$SyntaxError.buildMessage = function (expected, found) {\r\n var DESCRIBE_EXPECTATION_FNS = {\r\n literal: function (expectation) {\r\n return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";\r\n },\r\n\r\n \"class\": function (expectation) {\r\n var escapedParts = \"\",\r\n i;\r\n\r\n for (i = 0; i < expectation.parts.length; i++) {\r\n escapedParts += expectation.parts[i] instanceof Array ?\r\n classEscape(expectation.parts[i][0]) + \"-\" + classEscape(expectation.parts[i][1]) :\r\n classEscape(expectation.parts[i]);\r\n }\r\n\r\n return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";\r\n },\r\n\r\n any: function (expectation) {\r\n return \"any character\";\r\n },\r\n\r\n end: function (expectation) {\r\n return \"end of input\";\r\n },\r\n\r\n other: function (expectation) {\r\n return expectation.description;\r\n }\r\n };\r\n\r\n function hex(ch) {\r\n return ch.charCodeAt(0).toString(16).toUpperCase();\r\n }\r\n\r\n function literalEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function classEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\\]/g, '\\\\]')\r\n .replace(/\\^/g, '\\\\^')\r\n .replace(/-/g, '\\\\-')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function describeExpectation(expectation) {\r\n return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\r\n }\r\n\r\n function describeExpected(expected) {\r\n var descriptions = new Array(expected.length),\r\n i, j;\r\n\r\n for (i = 0; i < expected.length; i++) {\r\n descriptions[i] = describeExpectation(expected[i]);\r\n }\r\n\r\n descriptions.sort();\r\n\r\n if (descriptions.length > 0) {\r\n for (i = 1, j = 1; i < descriptions.length; i++) {\r\n if (descriptions[i - 1] !== descriptions[i]) {\r\n descriptions[j] = descriptions[i];\r\n j++;\r\n }\r\n }\r\n descriptions.length = j;\r\n }\r\n\r\n switch (descriptions.length) {\r\n case 1:\r\n return descriptions[0];\r\n\r\n case 2:\r\n return descriptions[0] + \" or \" + descriptions[1];\r\n\r\n default:\r\n return descriptions.slice(0, -1).join(\", \") +\r\n \", or \" +\r\n descriptions[descriptions.length - 1];\r\n }\r\n }\r\n\r\n function describeFound(found) {\r\n return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";\r\n }\r\n\r\n return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\r\n };\r\n\r\n function peg$parse(input, options) {\r\n options = options !== void 0 ? options : {};\r\n\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n var nOpenParentheses = input.split('(').length - 1;\r\n var nCloseParentheses = input.split(')').length - 1;\r\n\r\n if (nOpenParentheses !== nCloseParentheses) {\r\n throw peg$buildSimpleError('The number of opening parentheses does not match the number of closing parentheses.', 0);\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n var peg$FAILED = {},\r\n\r\n peg$startRuleFunctions = {\r\n chain: peg$parsechain\r\n },\r\n peg$startRuleFunction = peg$parsechain,\r\n\r\n peg$c0 = function (s) {\r\n var branches = [];\r\n var rings = [];\r\n\r\n for (var i = 0; i < s[1].length; i++) {\r\n branches.push(s[1][i]);\r\n }\r\n\r\n\r\n for (var i = 0; i < s[2].length; i++) {\r\n var bond = (s[2][i][0]) ? s[2][i][0] : '-';\r\n rings.push({\r\n 'bond': bond,\r\n 'id': s[2][i][1]\r\n });\r\n }\r\n\r\n for (var i = 0; i < s[3].length; i++) {\r\n branches.push(s[3][i]);\r\n }\r\n\r\n for (var i = 0; i < s[6].length; i++) {\r\n branches.push(s[6][i]);\r\n }\r\n\r\n return {\r\n 'atom': s[0],\r\n 'isBracket': s[0].element ? true : false,\r\n 'branches': branches,\r\n 'branchCount': branches.length,\r\n 'ringbonds': rings,\r\n 'ringbondCount': rings.length,\r\n 'bond': s[4] ? s[4] : '-',\r\n 'next': s[5],\r\n 'hasNext': s[5] ? true : false\r\n }\r\n\r\n return s;\r\n },\r\n peg$c1 = \"(\",\r\n peg$c2 = peg$literalExpectation(\"(\", false),\r\n peg$c3 = \")\",\r\n peg$c4 = peg$literalExpectation(\")\", false),\r\n peg$c5 = function (b) {\r\n var bond = (b[1]) ? b[1] : '-';\r\n b[2].branchBond = bond;\r\n return b[2]\r\n },\r\n peg$c6 = function (a) {\r\n return a;\r\n },\r\n peg$c7 = /^[\\-=#$:\\/\\\\.]/,\r\n peg$c8 = peg$classExpectation([\"-\", \"=\", \"#\", \"$\", \":\", \"/\", \"\\\\\", \".\"], false, false),\r\n peg$c9 = function (b) {\r\n return b;\r\n },\r\n peg$c10 = \"[\",\r\n peg$c11 = peg$literalExpectation(\"[\", false),\r\n peg$c12 = \"se\",\r\n peg$c13 = peg$literalExpectation(\"se\", false),\r\n peg$c14 = \"as\",\r\n peg$c15 = peg$literalExpectation(\"as\", false),\r\n peg$c16 = \"]\",\r\n peg$c17 = peg$literalExpectation(\"]\", false),\r\n peg$c18 = function (b) {\r\n return {\r\n 'isotope': b[1],\r\n 'element': b[2],\r\n 'chirality': b[3],\r\n 'hcount': b[4],\r\n 'charge': b[5],\r\n 'class': b[6]\r\n }\r\n },\r\n peg$c19 = \"B\",\r\n peg$c20 = peg$literalExpectation(\"B\", false),\r\n peg$c21 = \"r\",\r\n peg$c22 = peg$literalExpectation(\"r\", false),\r\n peg$c23 = \"C\",\r\n peg$c24 = peg$literalExpectation(\"C\", false),\r\n peg$c25 = \"l\",\r\n peg$c26 = peg$literalExpectation(\"l\", false),\r\n peg$c27 = /^[NOPSFI]/,\r\n peg$c28 = peg$classExpectation([\"N\", \"O\", \"P\", \"S\", \"F\", \"I\"], false, false),\r\n peg$c29 = function (o) {\r\n if (o.length > 1) return o.join('');\r\n return o;\r\n },\r\n peg$c30 = /^[bcnops]/,\r\n peg$c31 = peg$classExpectation([\"b\", \"c\", \"n\", \"o\", \"p\", \"s\"], false, false),\r\n peg$c32 = \"*\",\r\n peg$c33 = peg$literalExpectation(\"*\", false),\r\n peg$c34 = function (w) {\r\n return w;\r\n },\r\n peg$c35 = /^[A-Z]/,\r\n peg$c36 = peg$classExpectation([\r\n [\"A\", \"Z\"]\r\n ], false, false),\r\n peg$c37 = /^[a-z]/,\r\n peg$c38 = peg$classExpectation([\r\n [\"a\", \"z\"]\r\n ], false, false),\r\n peg$c39 = function (e) {\r\n return e.join('');\r\n },\r\n peg$c40 = \"%\",\r\n peg$c41 = peg$literalExpectation(\"%\", false),\r\n peg$c42 = /^[1-9]/,\r\n peg$c43 = peg$classExpectation([\r\n [\"1\", \"9\"]\r\n ], false, false),\r\n peg$c44 = /^[0-9]/,\r\n peg$c45 = peg$classExpectation([\r\n [\"0\", \"9\"]\r\n ], false, false),\r\n peg$c46 = function (r) {\r\n if (r.length == 1) return Number(r);\r\n return Number(r.join('').replace('%', ''));\r\n },\r\n peg$c47 = \"@\",\r\n peg$c48 = peg$literalExpectation(\"@\", false),\r\n peg$c49 = \"TH\",\r\n peg$c50 = peg$literalExpectation(\"TH\", false),\r\n peg$c51 = /^[12]/,\r\n peg$c52 = peg$classExpectation([\"1\", \"2\"], false, false),\r\n peg$c53 = \"AL\",\r\n peg$c54 = peg$literalExpectation(\"AL\", false),\r\n peg$c55 = \"SP\",\r\n peg$c56 = peg$literalExpectation(\"SP\", false),\r\n peg$c57 = /^[1-3]/,\r\n peg$c58 = peg$classExpectation([\r\n [\"1\", \"3\"]\r\n ], false, false),\r\n peg$c59 = \"TB\",\r\n peg$c60 = peg$literalExpectation(\"TB\", false),\r\n peg$c61 = \"OH\",\r\n peg$c62 = peg$literalExpectation(\"OH\", false),\r\n peg$c63 = function (c) {\r\n if (!c[1]) return '@';\r\n if (c[1] == '@') return '@@';\r\n\r\n return c[1].join('').replace(',', '');\r\n },\r\n peg$c64 = function (c) {\r\n return c;\r\n },\r\n peg$c65 = \"+\",\r\n peg$c66 = peg$literalExpectation(\"+\", false),\r\n peg$c67 = function (c) {\r\n if (!c[1]) return 1;\r\n if (c[1] != '+') return Number(c[1].join(''));\r\n return 2;\r\n },\r\n peg$c68 = \"-\",\r\n peg$c69 = peg$literalExpectation(\"-\", false),\r\n peg$c70 = function (c) {\r\n if (!c[1]) return -1;\r\n if (c[1] != '-') return -Number(c[1].join(''));\r\n return -2;\r\n },\r\n peg$c71 = \"H\",\r\n peg$c72 = peg$literalExpectation(\"H\", false),\r\n peg$c73 = function (h) {\r\n if (h[1]) return Number(h[1]);\r\n return 1;\r\n },\r\n peg$c74 = \":\",\r\n peg$c75 = peg$literalExpectation(\":\", false),\r\n peg$c76 = /^[0]/,\r\n peg$c77 = peg$classExpectation([\"0\"], false, false),\r\n peg$c78 = function (c) {\r\n return Number(c[1][0] + c[1][1].join(''));\r\n },\r\n peg$c79 = function (i) {\r\n return Number(i.join(''));\r\n },\r\n\r\n peg$currPos = 0,\r\n peg$savedPos = 0,\r\n peg$posDetailsCache = [{\r\n line: 1,\r\n column: 1\r\n }],\r\n peg$maxFailPos = 0,\r\n peg$maxFailExpected = [],\r\n peg$silentFails = 0,\r\n\r\n peg$result;\r\n\r\n if (\"startRule\" in options) {\r\n if (!(options.startRule in peg$startRuleFunctions)) {\r\n throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");\r\n }\r\n\r\n peg$startRuleFunction = peg$startRuleFunctions[options.startRule];\r\n }\r\n\r\n function text() {\r\n return input.substring(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function location() {\r\n return peg$computeLocation(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function expected(description, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildStructuredError(\r\n [peg$otherExpectation(description)],\r\n input.substring(peg$savedPos, peg$currPos),\r\n location\r\n );\r\n }\r\n\r\n function error(message, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildSimpleError(message, location);\r\n }\r\n\r\n function peg$literalExpectation(text, ignoreCase) {\r\n return {\r\n type: \"literal\",\r\n text: text,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$classExpectation(parts, inverted, ignoreCase) {\r\n return {\r\n type: \"class\",\r\n parts: parts,\r\n inverted: inverted,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$anyExpectation() {\r\n return {\r\n type: \"any\"\r\n };\r\n }\r\n\r\n function peg$endExpectation() {\r\n return {\r\n type: \"end\"\r\n };\r\n }\r\n\r\n function peg$otherExpectation(description) {\r\n return {\r\n type: \"other\",\r\n description: description\r\n };\r\n }\r\n\r\n function peg$computePosDetails(pos) {\r\n var details = peg$posDetailsCache[pos],\r\n p;\r\n\r\n if (details) {\r\n return details;\r\n } else {\r\n p = pos - 1;\r\n while (!peg$posDetailsCache[p]) {\r\n p--;\r\n }\r\n\r\n details = peg$posDetailsCache[p];\r\n details = {\r\n line: details.line,\r\n column: details.column\r\n };\r\n\r\n while (p < pos) {\r\n if (input.charCodeAt(p) === 10) {\r\n details.line++;\r\n details.column = 1;\r\n } else {\r\n details.column++;\r\n }\r\n\r\n p++;\r\n }\r\n\r\n peg$posDetailsCache[pos] = details;\r\n return details;\r\n }\r\n }\r\n\r\n function peg$computeLocation(startPos, endPos) {\r\n var startPosDetails = peg$computePosDetails(startPos),\r\n endPosDetails = peg$computePosDetails(endPos);\r\n\r\n return {\r\n start: {\r\n offset: startPos,\r\n line: startPosDetails.line,\r\n column: startPosDetails.column\r\n },\r\n end: {\r\n offset: endPos,\r\n line: endPosDetails.line,\r\n column: endPosDetails.column\r\n }\r\n };\r\n }\r\n\r\n function peg$fail(expected) {\r\n if (peg$currPos < peg$maxFailPos) {\r\n return;\r\n }\r\n\r\n if (peg$currPos > peg$maxFailPos) {\r\n peg$maxFailPos = peg$currPos;\r\n peg$maxFailExpected = [];\r\n }\r\n\r\n peg$maxFailExpected.push(expected);\r\n }\r\n\r\n function peg$buildSimpleError(message, location) {\r\n return new peg$SyntaxError(message, null, null, location);\r\n }\r\n\r\n function peg$buildStructuredError(expected, found, location) {\r\n return new peg$SyntaxError(\r\n peg$SyntaxError.buildMessage(expected, found),\r\n expected,\r\n found,\r\n location\r\n );\r\n }\r\n\r\n function peg$parsechain() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n s2 = peg$parseatom();\r\n if (s2 !== peg$FAILED) {\r\n s3 = [];\r\n s4 = peg$parsebranch();\r\n while (s4 !== peg$FAILED) {\r\n s3.push(s4);\r\n s4 = peg$parsebranch();\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = [];\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n while (s5 !== peg$FAILED) {\r\n s4.push(s5);\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n s6 = peg$parsebranch();\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n s6 = peg$parsebranch();\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsechain();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = [];\r\n s9 = peg$parsebranch();\r\n while (s9 !== peg$FAILED) {\r\n s8.push(s9);\r\n s9 = peg$parsebranch();\r\n }\r\n if (s8 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c0(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebranch() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 40) {\r\n s2 = peg$c1;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c2);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parsebond();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = peg$parsechain();\r\n if (s4 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 41) {\r\n s5 = peg$c3;\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c4);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c5(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseatom() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseorganicsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsearomaticsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsebracketatom();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebond() {\r\n var s0, s1;\r\n s0 = peg$currPos;\r\n if (peg$c7.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n\r\n // Hack to resolve problem caused by:\r\n // O=C(N[C@@H](CC(O)=O)C(N[C@H](C1=CC=C(O)C=C1)C(N[C@@H](CC(O)=O)C(NCC(N[C@@H](C(N[C@@H]([C@H](C)CC(O)=O)C(N/C(C(O[C@H](C)[C@@H]2NC([C@H](CO)NC(C(O3)C3CCC)=O)=O)=O)=C\\\\\\\\C4=CNC5=C4C=CC=C5)=O)=O)[C@H](O)C(N)=O)=O)=O)=O)=O)[C@H](CC(O)=O)NC([C@@H](CC6=CNC7=C6C=CC=C7)NC2=O)=O\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n if (s1 === input.charAt(peg$currPos + 1)) {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n throw peg$buildSimpleError('The parser encountered a bond repetition.', peg$currPos + 1);\r\n }\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c8);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c9(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebracketatom() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 91) {\r\n s2 = peg$c10;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c11);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parseisotope();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c12) {\r\n s4 = peg$c12;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c13);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c14) {\r\n s4 = peg$c14;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c15);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsearomaticsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parseelementsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = peg$parsechiral();\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsehcount();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsecharge();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = peg$parseclass();\r\n if (s8 === peg$FAILED) {\r\n s8 = null;\r\n }\r\n if (s8 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 93) {\r\n s9 = peg$c16;\r\n peg$currPos++;\r\n } else {\r\n s9 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c17);\r\n }\r\n }\r\n if (s9 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8, s9];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c18(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseorganicsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 66) {\r\n s2 = peg$c19;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c20);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 114) {\r\n s3 = peg$c21;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c22);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 67) {\r\n s2 = peg$c23;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c24);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 108) {\r\n s3 = peg$c25;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c26);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c27.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c28);\r\n }\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c29(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsearomaticsymbol() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (peg$c30.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c31);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsewildcard() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 42) {\r\n s1 = peg$c32;\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c33);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c34(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseelementsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c35.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c36);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c37.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c38);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c39(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsering() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 37) {\r\n s2 = peg$c40;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c41);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c46(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsechiral() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s2 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s3 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c49) {\r\n s4 = peg$c49;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c50);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c53) {\r\n s4 = peg$c53;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c54);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c55) {\r\n s4 = peg$c55;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c56);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c57.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c58);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c59) {\r\n s4 = peg$c59;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c60);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c61) {\r\n s4 = peg$c61;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c62);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c63(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsecharge() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseposcharge();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsenegcharge();\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c64(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseposcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s2 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s3 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c67(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsenegcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s2 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s3 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c70(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsehcount() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 72) {\r\n s2 = peg$c71;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c72);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c73(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseclass() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 58) {\r\n s2 = peg$c74;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c75);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n if (peg$c76.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c77);\r\n }\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c78(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseisotope() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = null;\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c79(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n peg$result = peg$startRuleFunction();\r\n\r\n if (peg$result !== peg$FAILED && peg$currPos === input.length) {\r\n return peg$result;\r\n } else {\r\n if (peg$result !== peg$FAILED && peg$currPos < input.length) {\r\n peg$fail(peg$endExpectation());\r\n }\r\n\r\n throw peg$buildStructuredError(\r\n peg$maxFailExpected,\r\n peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,\r\n peg$maxFailPos < input.length ?\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) :\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n SyntaxError: peg$SyntaxError,\r\n parse: peg$parse\r\n };\r\n})();","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Vertex = require('./Vertex')\r\nconst RingConnection = require('./RingConnection')\r\n\r\n/** \r\n * A class representing a ring.\r\n * \r\n * @property {Number} id The id of this ring.\r\n * @property {Number[]} members An array containing the vertex ids of the ring members.\r\n * @property {Number[]} edges An array containing the edge ids of the edges between the ring members.\r\n * @property {Number[]} insiders An array containing the vertex ids of the vertices contained within the ring if it is a bridged ring.\r\n * @property {Number[]} neighbours An array containing the ids of neighbouring rings.\r\n * @property {Boolean} positioned A boolean indicating whether or not this ring has been positioned.\r\n * @property {Vector2} center The center of this ring.\r\n * @property {Ring[]} rings The rings contained within this ring if this ring is bridged.\r\n * @property {Boolean} isBridged A boolean whether or not this ring is bridged.\r\n * @property {Boolean} isPartOfBridged A boolean whether or not this ring is part of a bridge ring.\r\n * @property {Boolean} isSpiro A boolean whether or not this ring is part of a spiro.\r\n * @property {Boolean} isFused A boolean whether or not this ring is part of a fused ring.\r\n * @property {Number} centralAngle The central angle of this ring.\r\n * @property {Boolean} canFlip A boolean indicating whether or not this ring allows flipping of attached vertices to the inside of the ring.\r\n */\r\nclass Ring {\r\n /**\r\n * The constructor for the class Ring.\r\n *\r\n * @param {Number[]} members An array containing the vertex ids of the members of the ring to be created.\r\n */\r\n constructor(members) {\r\n this.id = null;\r\n this.members = members;\r\n this.edges = [];\r\n this.insiders = [];\r\n this.neighbours = [];\r\n this.positioned = false;\r\n this.center = new Vector2(0, 0);\r\n this.rings = [];\r\n this.isBridged = false;\r\n this.isPartOfBridged = false;\r\n this.isSpiro = false;\r\n this.isFused = false;\r\n this.centralAngle = 0.0;\r\n this.canFlip = true;\r\n }\r\n \r\n /**\r\n * Clones this ring and returns the clone.\r\n *\r\n * @returns {Ring} A clone of this ring.\r\n */\r\n clone() {\r\n let clone = new Ring(this.members);\r\n\r\n clone.id = this.id;\r\n clone.insiders = ArrayHelper.clone(this.insiders);\r\n clone.neighbours = ArrayHelper.clone(this.neighbours);\r\n clone.positioned = this.positioned;\r\n clone.center = this.center.clone();\r\n clone.rings = ArrayHelper.clone(this.rings);\r\n clone.isBridged = this.isBridged;\r\n clone.isPartOfBridged = this.isPartOfBridged;\r\n clone.isSpiro = this.isSpiro;\r\n clone.isFused = this.isFused;\r\n clone.centralAngle = this.centralAngle;\r\n clone.canFlip = this.canFlip;\r\n\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns the size (number of members) of this ring.\r\n *\r\n * @returns {Number} The size (number of members) of this ring.\r\n */\r\n getSize() {\r\n return this.members.length;\r\n }\r\n\r\n /**\r\n * Gets the polygon representation (an array of the ring-members positional vectors) of this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices representing the current molecule.\r\n * @returns {Vector2[]} An array of the positional vectors of the ring members.\r\n */\r\n getPolygon(vertices) {\r\n let polygon = [];\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n polygon.push(vertices[this.members[i]].position);\r\n }\r\n\r\n return polygon;\r\n }\r\n\r\n /**\r\n * Returns the angle of this ring in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n return Math.PI - this.centralAngle;\r\n }\r\n\r\n /**\r\n * Loops over the members of this ring from a given start position in a direction opposite to the vertex id passed as the previousId.\r\n *\r\n * @param {Vertex[]} vertices The vertices associated with the current molecule.\r\n * @param {Function} callback A callback with the current vertex id as a parameter.\r\n * @param {Number} startVertexId The vertex id of the start vertex.\r\n * @param {Number} previousVertexId The vertex id of the previous vertex (the loop calling the callback function will run in the opposite direction of this vertex).\r\n */\r\n eachMember(vertices, callback, startVertexId, previousVertexId) {\r\n startVertexId = startVertexId || startVertexId === 0 ? startVertexId : this.members[0];\r\n let current = startVertexId;\r\n let max = 0;\r\n\r\n while (current != null && max < 100) {\r\n let prev = current;\r\n \r\n callback(prev);\r\n current = vertices[current].getNextInRing(vertices, this.id, previousVertexId);\r\n previousVertexId = prev;\r\n \r\n // Stop while loop when arriving back at the start vertex\r\n if (current == startVertexId) {\r\n current = null;\r\n }\r\n\r\n max++;\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array containing the neighbouring rings of this ring ordered by ring size.\r\n *\r\n * @param {RingConnection[]} ringConnections An array of ring connections associated with the current molecule.\r\n * @returns {Object[]} An array of neighbouring rings sorted by ring size. Example: { n: 5, neighbour: 1 }.\r\n */\r\n getOrderedNeighbours(ringConnections) {\r\n let orderedNeighbours = Array(this.neighbours.length);\r\n \r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n let vertices = RingConnection.getVertices(ringConnections, this.id, this.neighbours[i]);\r\n \r\n orderedNeighbours[i] = {\r\n n: vertices.length,\r\n neighbour: this.neighbours[i]\r\n };\r\n }\r\n\r\n orderedNeighbours.sort(function (a, b) {\r\n // Sort highest to lowest\r\n return b.n - a.n;\r\n });\r\n\r\n return orderedNeighbours;\r\n }\r\n\r\n /**\r\n * Check whether this ring is an implicitly defined benzene-like (e.g. C1=CC=CC=C1) with 6 members and 3 double bonds.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring is an implicitly defined benzene-like.\r\n */\r\n isBenzeneLike(vertices) {\r\n let db = this.getDoubleBondCount(vertices);\r\n let length = this.members.length;\r\n\r\n return db === 3 && length === 6 ||\r\n db === 2 && length === 5 ;\r\n }\r\n\r\n /**\r\n * Get the number of double bonds inside this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Number} The number of double bonds inside this ring.\r\n */\r\n getDoubleBondCount(vertices) {\r\n let doubleBondCount = 0;\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n let atom = vertices[this.members[i]].value;\r\n\r\n if (atom.bondType === '=' || atom.branchBond === '=') {\r\n doubleBondCount++;\r\n }\r\n }\r\n\r\n return doubleBondCount;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring contains a member with a given vertex id.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not this ring contains a member with the given vertex id.\r\n */\r\n contains(vertexId) {\r\n for (let i = 0; i < this.members.length; i++) {\r\n if (this.members[i] == vertexId) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n\r\nmodule.exports = Ring;","//@ts-check\r\nconst Vertex = require('./Vertex')\r\nconst Ring = require('./Ring')\r\n\r\n/** \r\n * A class representing a ring connection.\r\n * \r\n * @property {Number} id The id of this ring connection.\r\n * @property {Number} firstRingId A ring id.\r\n * @property {Number} secondRingId A ring id.\r\n * @property {Set} vertices A set containing the vertex ids participating in the ring connection.\r\n */\r\nclass RingConnection {\r\n /**\r\n * The constructor for the class RingConnection.\r\n *\r\n * @param {Ring} firstRing A ring.\r\n * @param {Ring} secondRing A ring.\r\n */\r\n constructor(firstRing, secondRing) {\r\n this.id = null;\r\n this.firstRingId = firstRing.id;\r\n this.secondRingId = secondRing.id;\r\n this.vertices = new Set();\r\n\r\n for (var m = 0; m < firstRing.members.length; m++) {\r\n let c = firstRing.members[m];\r\n\r\n for (let n = 0; n < secondRing.members.length; n++) {\r\n let d = secondRing.members[n];\r\n\r\n if (c === d) {\r\n this.addVertex(c);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adding a vertex to the ring connection.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n */\r\n addVertex(vertexId) {\r\n this.vertices.add(vertexId);\r\n }\r\n\r\n /**\r\n * Update the ring id of this ring connection that is not the ring id supplied as the second argument.\r\n *\r\n * @param {Number} ringId A ring id. The new ring id to be set.\r\n * @param {Number} otherRingId A ring id. The id that is NOT to be updated.\r\n */\r\n updateOther(ringId, otherRingId) {\r\n if (this.firstRingId === otherRingId) {\r\n this.secondRingId = ringId;\r\n } else {\r\n this.firstRingId = ringId;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.\r\n * \r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.\r\n */\r\n containsRing(ringId) {\r\n return this.firstRingId === ringId || this.secondRingId === ringId;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring connection is a bridge in a bridged ring.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.\r\n */\r\n isBridge(vertices) {\r\n if (this.vertices.size > 2) {\r\n return true;\r\n }\r\n\r\n for (let vertexId of this.vertices) {\r\n if(vertices[vertexId].value.rings.length > 2) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two rings are connected by a bridged bond.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.\r\n */\r\n static isBridge(ringConnections, vertices, firstRingId, secondRingId) {\r\n let ringConnection = null;\r\n \r\n for (let i = 0; i < ringConnections.length; i++) {\r\n ringConnection = ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return ringConnection.isBridge(vertices);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Retruns the neighbouring rings of a given ring.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array of ring ids of neighbouring rings.\r\n */\r\n static getNeighbours(ringConnections, ringId) {\r\n let neighbours = [];\r\n\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n \r\n if (ringConnection.firstRingId === ringId) {\r\n neighbours.push(ringConnection.secondRingId);\r\n } else if (ringConnection.secondRingId === ringId) {\r\n neighbours.push(ringConnection.firstRingId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Returns an array of vertex ids associated with a given ring connection.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Number[]} An array of vertex ids associated with the ring connection.\r\n */\r\n static getVertices(ringConnections, firstRingId, secondRingId) {\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return [...ringConnection.vertices];\r\n }\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = RingConnection","//@ts-check\r\nconst Graph = require('./Graph')\r\n\r\n/** A class encapsulating the functionality to find the smallest set of smallest rings in a graph. */\r\nclass SSSR {\r\n /**\r\n * Returns an array containing arrays, each representing a ring from the smallest set of smallest rings in the graph.\r\n * \r\n * @param {Graph} graph A Graph object.\r\n * @param {Boolean} [experimental=false] Whether or not to use experimental SSSR.\r\n * @returns {Array[]} An array containing arrays, each representing a ring from the smallest set of smallest rings in the group.\r\n */\r\n static getRings(graph, experimental=false) {\r\n let adjacencyMatrix = graph.getComponentsAdjacencyMatrix();\r\n if (adjacencyMatrix.length === 0) {\r\n return null;\r\n }\r\n\r\n let connectedComponents = Graph.getConnectedComponents(adjacencyMatrix);\r\n let rings = Array();\r\n\r\n for (var i = 0; i < connectedComponents.length; i++) {\r\n let connectedComponent = connectedComponents[i];\r\n let ccAdjacencyMatrix = graph.getSubgraphAdjacencyMatrix([...connectedComponent]);\r\n\r\n let arrBondCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n let arrRingCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n arrRingCount[j] = 0;\r\n arrBondCount[j] = 0;\r\n\r\n for (var k = 0; k < ccAdjacencyMatrix[j].length; k++) {\r\n arrBondCount[j] += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n // Get the edge number and the theoretical number of rings in SSSR\r\n let nEdges = 0;\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n for (var k = j + 1; k < ccAdjacencyMatrix.length; k++) {\r\n nEdges += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n let nSssr = nEdges - ccAdjacencyMatrix.length + 1;\r\n\r\n // console.log(nEdges, ccAdjacencyMatrix.length, nSssr);\r\n // console.log(SSSR.getEdgeList(ccAdjacencyMatrix));\r\n // console.log(ccAdjacencyMatrix);\r\n\r\n // If all vertices have 3 incident edges, calculate with different formula (see Euler)\r\n let allThree = true;\r\n for (var j = 0; j < arrBondCount.length; j++) {\r\n if (arrBondCount[j] !== 3) {\r\n allThree = false;\r\n }\r\n }\r\n\r\n if (allThree) {\r\n nSssr = 2.0 + nEdges - ccAdjacencyMatrix.length;\r\n }\r\n\r\n // All vertices are part of one ring if theres only one ring.\r\n if (nSssr === 1) {\r\n rings.push([...connectedComponent]);\r\n continue;\r\n }\r\n \r\n if (experimental) {\r\n nSssr = 999;\r\n }\r\n\r\n let { d, pe, pe_prime } = SSSR.getPathIncludedDistanceMatrices(ccAdjacencyMatrix);\r\n let c = SSSR.getRingCandidates(d, pe, pe_prime);\r\n let sssr = SSSR.getSSSR(c, d, ccAdjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nSssr);\r\n\r\n for (var j = 0; j < sssr.length; j++) {\r\n let ring = Array(sssr[j].size);\r\n let index = 0;\r\n\r\n for (let val of sssr[j]) {\r\n // Get the original id of the vertex back\r\n ring[index++] = connectedComponent[val];\r\n }\r\n\r\n rings.push(ring);\r\n }\r\n }\r\n \r\n\r\n // So, for some reason, this would return three rings for C1CCCC2CC1CCCC2, which is wrong\r\n // As I don't have time to fix this properly, it will stay in. I'm sorry next person who works\r\n // on it. At that point it might be best to reimplement the whole SSSR thing...\r\n return rings;\r\n }\r\n\r\n /**\r\n * Creates a printable string from a matrix (2D array).\r\n * \r\n * @param {Array[]} matrix A 2D array.\r\n * @returns {String} A string representing the matrix.\r\n */\r\n static matrixToString(matrix) {\r\n let str = '';\r\n\r\n for (var i = 0; i < matrix.length; i++) {\r\n for (var j = 0; j < matrix[i].length; j++) {\r\n str += matrix[i][j] + ' ';\r\n }\r\n\r\n str += '\\n';\r\n }\r\n\r\n return str;\r\n }\r\n\r\n /**\r\n * Returnes the two path-included distance matrices used to find the sssr.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Object} The path-included distance matrices. { p1, p2 }\r\n */\r\n static getPathIncludedDistanceMatrices(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let d = Array(length);\r\n let pe = Array(length);\r\n let pe_prime = Array(length);\r\n var l = 0;\r\n var m = 0;\r\n var n = 0;\r\n\r\n var i = length;\r\n while (i--) {\r\n d[i] = Array(length);\r\n pe[i] = Array(length);\r\n pe_prime[i] = Array(length);\r\n\r\n var j = length;\r\n while (j--) {\r\n d[i][j] = (i === j || adjacencyMatrix[i][j] === 1) ? adjacencyMatrix[i][j] : Number.POSITIVE_INFINITY;\r\n\r\n if (d[i][j] === 1) {\r\n pe[i][j] = [[[i, j]]];\r\n } else {\r\n pe[i][j] = Array();\r\n }\r\n\r\n pe_prime[i][j] = Array();\r\n }\r\n }\r\n\r\n var k = length;\r\n var j;\r\n while (k--) {\r\n i = length;\r\n while (i--) {\r\n j = length;\r\n while (j--) {\r\n const previousPathLength = d[i][j];\r\n const newPathLength = d[i][k] + d[k][j];\r\n\r\n if (previousPathLength > newPathLength) {\r\n var l, m, n;\r\n if (previousPathLength === newPathLength + 1) {\r\n pe_prime[i][j] = [pe[i][j].length];\r\n l = pe[i][j].length\r\n while (l--) {\r\n pe_prime[i][j][l] = [pe[i][j][l].length];\r\n m = pe[i][j][l].length\r\n while (m--) {\r\n pe_prime[i][j][l][m] = [pe[i][j][l][m].length];\r\n n = pe[i][j][l][m].length;\r\n while (n--) {\r\n pe_prime[i][j][l][m][n] = [pe[i][j][l][m][0], pe[i][j][l][m][1]];\r\n }\r\n }\r\n }\r\n } else {\r\n pe_prime[i][j] = Array();\r\n }\r\n\r\n d[i][j] = newPathLength;\r\n\r\n pe[i][j] = [[]];\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[k][j][0][l]);\r\n }\r\n } else if (previousPathLength === newPathLength) {\r\n if (pe[i][k].length && pe[k][j].length) {\r\n var l;\r\n if (pe[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j][0] = tmp\r\n }\r\n }\r\n } else if (previousPathLength === newPathLength - 1) {\r\n var l;\r\n if (pe_prime[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j][0] = tmp;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n d: d,\r\n pe: pe,\r\n pe_prime: pe_prime\r\n };\r\n }\r\n\r\n /**\r\n * Get the ring candidates from the path-included distance matrices.\r\n * \r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @returns {Array[]} The ring candidates.\r\n */\r\n static getRingCandidates(d, pe, pe_prime) {\r\n let length = d.length;\r\n let candidates = Array();\r\n let c = 0;\r\n\r\n for (let i = 0; i < length; i++) {\r\n for (let j = 0; j < length; j++) {\r\n if (d[i][j] === 0 || (pe[i][j].length === 1 && pe_prime[i][j] === 0)) {\r\n continue;\r\n } else {\r\n // c is the number of vertices in the cycle.\r\n if (pe_prime[i][j].length !== 0) {\r\n c = 2 * (d[i][j] + 0.5);\r\n } else {\r\n c = 2 * d[i][j];\r\n }\r\n\r\n if (c !== Infinity) {\r\n candidates.push([c, pe[i][j], pe_prime[i][j]]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Candidates have to be sorted by c\r\n candidates.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n\r\n return candidates;\r\n }\r\n\r\n /**\r\n * Searches the candidates for the smallest set of smallest rings.\r\n * \r\n * @param {Array[]} c The candidates.\r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @param {Number} nsssr The theoretical number of rings in the graph.\r\n * @returns {Set[]} The smallest set of smallest rings.\r\n */\r\n static getSSSR(c, d, adjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nsssr) {\r\n let cSssr = Array();\r\n let allBonds = Array();\r\n\r\n for (let i = 0; i < c.length; i++) {\r\n if (c[i][0] % 2 !== 0) {\r\n for (let j = 0; j < c[i][2].length; j++) {\r\n let bonds = c[i][1][0].concat(c[i][2][j]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n } else {\r\n for (let j = 0; j < c[i][1].length - 1; j++) {\r\n let bonds = c[i][1][j].concat(c[i][1][j + 1]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return cSssr;\r\n }\r\n\r\n /**\r\n * Returns the number of edges in a graph defined by an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of edges in the graph defined by the adjacency matrix.\r\n */\r\n static getEdgeCount(adjacencyMatrix) {\r\n let edgeCount = 0;\r\n let length = adjacencyMatrix.length;\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeCount++;\r\n }\r\n }\r\n }\r\n\r\n return edgeCount;\r\n }\r\n\r\n /**\r\n * Returns an edge list constructed form an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Array[]} An edge list. E.g. [ [ 0, 1 ], ..., [ 16, 2 ] ]\r\n */\r\n static getEdgeList(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let edgeList = Array();\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeList.push([i, j]);\r\n }\r\n }\r\n }\r\n\r\n return edgeList;\r\n }\r\n\r\n /**\r\n * Return a set of vertex indices contained in an array of bonds.\r\n * \r\n * @param {Array} bonds An array of bonds. A bond is defined as [ sourceVertexId, targetVertexId ].\r\n * @returns {Set} An array of vertices.\r\n */\r\n static bondsToAtoms(bonds) {\r\n let atoms = new Set();\r\n\r\n var i = bonds.length;\r\n while (i--) {\r\n atoms.add(bonds[i][0]);\r\n atoms.add(bonds[i][1]);\r\n }\r\n return atoms;\r\n }\r\n\r\n /**\r\n * Returns the number of bonds within a set of atoms.\r\n * \r\n * @param {Set} atoms An array of atom ids.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of bonds in a set of atoms.\r\n */\r\n static getBondCount(atoms, adjacencyMatrix) {\r\n let count = 0;\r\n for (let u of atoms) {\r\n for (let v of atoms) {\r\n if (u === v) {\r\n continue;\r\n }\r\n count += adjacencyMatrix[u][v]\r\n }\r\n }\r\n\r\n return count / 2;\r\n }\r\n\r\n /**\r\n * Checks whether or not a given path already exists in an array of paths.\r\n * \r\n * @param {Set[]} pathSets An array of sets each representing a path.\r\n * @param {Set} pathSet A set representing a path.\r\n * @param {Array[]} bonds The bonds associated with the current path.\r\n * @param {Array[]} allBonds All bonds currently associated with rings in the SSSR set.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @returns {Boolean} A boolean indicating whether or not a give path is contained within a set.\r\n */\r\n static pathSetsContain(pathSets, pathSet, bonds, allBonds, arrBondCount, arrRingCount) {\r\n var i = pathSets.length;\r\n while (i--) {\r\n if (SSSR.isSupersetOf(pathSet, pathSets[i])) {\r\n return true;\r\n }\r\n\r\n if (pathSets[i].size !== pathSet.size) {\r\n continue;\r\n }\r\n\r\n if (SSSR.areSetsEqual(pathSets[i], pathSet)) {\r\n return true;\r\n }\r\n }\r\n\r\n // Check if the edges from the candidate are already all contained within the paths of the set of paths.\r\n // TODO: For some reason, this does not replace the isSupersetOf method above -> why?\r\n let count = 0;\r\n let allContained = false;\r\n i = bonds.length;\r\n while (i--) {\r\n var j = allBonds.length;\r\n while (j--) {\r\n if (bonds[i][0] === allBonds[j][0] && bonds[i][1] === allBonds[j][1] ||\r\n bonds[i][1] === allBonds[j][0] && bonds[i][0] === allBonds[j][1]) {\r\n count++;\r\n }\r\n\r\n if (count === bonds.length) {\r\n allContained = true;\r\n }\r\n }\r\n }\r\n\r\n // If all the bonds and thus vertices are already contained within other rings\r\n // check if there's one vertex with ringCount < bondCount\r\n let specialCase = false;\r\n if (allContained) {\r\n for (let element of pathSet) {\r\n if (arrRingCount[element] < arrBondCount[element]) {\r\n specialCase = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (allContained && !specialCase) {\r\n return true;\r\n }\r\n\r\n // Update the ring counts for the vertices\r\n for (let element of pathSet) {\r\n arrRingCount[element]++;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two sets are equal (contain the same elements).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not the two sets are equal.\r\n */\r\n static areSetsEqual(setA, setB) {\r\n if (setA.size !== setB.size) {\r\n return false;\r\n }\r\n\r\n for (let element of setA) {\r\n if (!setB.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Checks whether or not a set (setA) is a superset of another set (setB).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not setB is a superset of setA.\r\n */\r\n static isSupersetOf(setA, setB) {\r\n for (var element of setB) {\r\n if (!setA.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\nmodule.exports = SSSR;","//@ts-check\r\n\r\nclass SequenceType {\r\n\r\n static get VALUES() {\r\n return {\r\n LINEAR: \"linear\",\r\n CYCLIC: \"cyclic\",\r\n BRANCH: \"branched\",\r\n BRANCH_CYCLIC: \"branch-cyclic\",\r\n LINEAR_POLYKETIDE: \"linear-polyketide\",\r\n CYCLIC_POLYKETIDE: \"cyclic-polyketide\",\r\n OTHER: \"other\",\r\n }\r\n }\r\n\r\n static getTypeFromValues(isCyclic, isBranch, isOther) {\r\n if (isOther) { return this.VALUES.OTHER;}\r\n if (!isCyclic && !isBranch) {\r\n return this.VALUES.LINEAR;\r\n } else if(isCyclic && !isBranch) {\r\n return this.VALUES.CYCLIC;\r\n } else if (!isCyclic) {\r\n return this.VALUES.BRANCH;\r\n } else {\r\n return this.VALUES.BRANCH_CYCLIC;\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = SequenceType;\r\n","//@ts-check\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst VertexState = require('./VertexState');\r\nconst Neighbour = require('./Neighbour');\r\nconst Direction = require('./Direction');\r\n\r\nclass SmallGraph {\r\n\r\n constructor() {\r\n this._nodes = [];\r\n this.isOther = false;\r\n this._branch = false;\r\n this.isCyclic = false;\r\n this.isBranched = false;\r\n this.sequenceType = SequenceType.VALUES.LINEAR;\r\n this._nodeOnRing = null;\r\n }\r\n\r\n addVertex(node) {\r\n this._nodes.push(node);\r\n }\r\n\r\n addNeighbour(nodeId, neighbour, direction) {\r\n this._nodes[nodeId].addNeighbour(new Neighbour(neighbour, direction));\r\n }\r\n\r\n dfsInitialization() {\r\n this._nodes.forEach(e => e.vertexState = VertexState.VALUES.NOT_FOUND);\r\n }\r\n\r\n getSourceNode() {\r\n let ends = [];\r\n for (let index = 0; index < this._nodes.length; ++index) {\r\n if (this._nodes[index].neighbours.length === 1) {\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.C) {\r\n return this._nodes[index];\r\n }\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.POLYKETIDE) {\r\n return this._nodes[index];\r\n }\r\n ends.push(this._nodes[index]);\r\n }\r\n }\r\n if (ends.length > 0) {\r\n return ends[0];\r\n }\r\n return null;\r\n }\r\n\r\n oneCyclic() {\r\n if (this._nodes.length === 0) {\r\n return false;\r\n }\r\n this.dfsInitialization();\r\n this.isCyclic = false;\r\n this.dfsCyclic(this._nodes[0], -1);\r\n }\r\n\r\n dfsCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = vertex;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.neighbours.length; ++i) {\r\n if (vertexFromId !== vertex.neighbours[i].neighbour) {\r\n this.dfsCyclic(this._nodes[vertex.neighbours[i].neighbour], vertex.id);\r\n }\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSequenceStart() {\r\n if (this._nodes.length === 0) {\r\n return;\r\n }\r\n this.dfsInitialization();\r\n this.sequence = \"\";\r\n if (this.isCyclic) {\r\n this.findRing(this._nodeOnRing);\r\n this.dfsSequenceCyclic(this._nodeOnRing);\r\n } else {\r\n let sourceNode = this.getSourceNode();\r\n if (sourceNode !== null) {\r\n this.dfsSequence(this.getSourceNode(), -1);\r\n } else {\r\n this.sequenceType = 'other';\r\n this.isOther = true;\r\n return;\r\n }\r\n }\r\n if (this.sequence.charAt(this.sequence.length - 1) === '-') {\r\n this.sequence = this.sequence.substr(0, this.sequence.length - 1);\r\n }\r\n this.sequenceType = SequenceType.getTypeFromValues(this.isCyclic, this.isBranched, this.isOther);\r\n }\r\n\r\n arrayContainsTimes(array, searchValue, times) {\r\n let cnt = 0;\r\n for (let index = 0; index < array.length; ++index) {\r\n if (array[index].neighbour === searchValue) {\r\n cnt++;\r\n if (cnt === times) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n findRing(start) {\r\n let queue = [];\r\n let firstPath = [start.id];\r\n let firstPass = true;\r\n queue.push(firstPath);\r\n while (queue.length !== 0) {\r\n let path = queue.pop();\r\n let last = path[path.length - 1];\r\n let node = this._nodes[last];\r\n if (node.id === start.id && !firstPass) {\r\n if (path.length === 3 && path[0] === path[2] && !this.arrayContainsTimes(this._nodes[path[0]].neighbours, path[1], 2)) {\r\n continue;\r\n }\r\n path.forEach(v => this._nodes[v].onRing = true);\r\n continue;\r\n }\r\n node.neighbours.forEach(\r\n neighbour => {\r\n if (!path.some(e => e === neighbour.neighbour) || neighbour.neighbour === start.id) {\r\n let newPath = [...path];\r\n newPath.push(neighbour.neighbour);\r\n queue.push(newPath);\r\n }\r\n }\r\n );\r\n firstPass = false;\r\n }\r\n }\r\n\r\n sortByRingPreference(array) {\r\n let sortedArray = [...array];\r\n sortedArray.sort((a, b) => {\r\n if (this._nodes[a.neighbour].onRing === this._nodes[b.neighbour].onRing) {\r\n if (a.direction > b.direction) {\r\n return -1;\r\n } else if (a.direction < b.direction) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n } else if (this._nodes[a.neighbour].onRing) {\r\n return 1;\r\n } else {\r\n return -1;\r\n }\r\n });\r\n return sortedArray;\r\n }\r\n\r\n dfsSequenceCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n let sortedNeighbours = this.sortByRingPreference(vertex.neighbours);\r\n for (let index = 0; index < sortedNeighbours.length; ++index) {\r\n if (vertexFromId === sortedNeighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequenceCyclic(this._nodes[sortedNeighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n printVertex(vertexId) {\r\n this.sequence += `[${vertexId}]`;\r\n }\r\n\r\n printDash() {\r\n if (']' === this.sequence[this.sequence.length - 1]) {\r\n this.sequence += '-';\r\n }\r\n }\r\n\r\n printLeftBrace(vertex) {\r\n if (vertex.neighbours.length > 2) {\r\n if (this.isBranched) {\r\n this.isOther = true;\r\n }\r\n this.sequence += '\\\\(';\r\n this._branch = true;\r\n this.isBranched = true;\r\n }\r\n }\r\n\r\n printRightBrace() {\r\n if (this._branch) {\r\n this.sequence += '\\\\)';\r\n this._branch = false;\r\n }\r\n }\r\n\r\n dfsSequence(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n for (let index = 0; index < vertex.neighbours.length; ++index) {\r\n if (vertexFromId === vertex.neighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequence(this._nodes[vertex.neighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n}\r\n\r\nmodule.exports = SmallGraph;\r\n","// we use the drawer to do all the preprocessing. then we take over the drawing\r\n// portion to output to svg\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Atom = require('./Atom');\r\nconst Drawer = require('./Drawer');\r\nconst Graph = require('./Graph');\r\nconst Line = require('./Line');\r\nconst SvgWrapper = require('./SvgWrapper');\r\nconst ThemeManager = require('./ThemeManager');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgDrawer {\r\n constructor(options) {\r\n this.preprocessor = new Drawer(options);\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to an svg element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML svg element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n\r\n * @returns {Oject} The dimensions of the drawing in { width, height }\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n let preprocessor = this.preprocessor;\r\n\r\n preprocessor.initDraw(data, themeName, infoOnly);\r\n\r\n if (!infoOnly) {\r\n this.themeManager = new ThemeManager(this.preprocessor.opts.themes, themeName);\r\n this.svgWrapper = new SvgWrapper(this.themeManager, target, this.preprocessor.opts);\r\n }\r\n\r\n preprocessor.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.svgWrapper.determineDimensions(preprocessor.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(preprocessor.opts.debug);\r\n this.drawVertices(preprocessor.opts.debug);\r\n\r\n if (preprocessor.opts.debug) {\r\n console.log(preprocessor.graph);\r\n console.log(preprocessor.rings);\r\n console.log(preprocessor.ringConnections);\r\n }\r\n\r\n return this.svgWrapper.constructSvg();\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let preprocessor = this.preprocessor,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n drawn = Array(this.preprocessor.graph.edges.length);\r\n\r\n drawn.fill(false);\r\n\r\n graph.traverseBF(0, vertex => {\r\n let edges = graph.getEdges(vertex.id);\r\n for (var i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n this.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let ring = rings[i];\r\n\r\n if (preprocessor.isRingAromatic(ring)) {\r\n this.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bond.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n svgWrapper = this.svgWrapper,\r\n edge = preprocessor.graph.edges[edgeId],\r\n vertexA = preprocessor.graph.vertices[edge.sourceId],\r\n vertexB = preprocessor.graph.vertices[edge.targetId],\r\n elementA = vertexA.value.element,\r\n elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && preprocessor.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position,\r\n b = vertexB.position,\r\n normals = preprocessor.getEdgeNormals(edge),\r\n // Create a point on each side of the line\r\n sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || preprocessor.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && preprocessor.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = preprocessor.areVerticesInSameRing(vertexA, vertexB);\r\n let s = preprocessor.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(opts.bondSpacing);\r\n normals[1].multiplyScalar(opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line = null;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n }\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n // preprocessor.canvasWrapper.drawLine(line, true);\r\n svgWrapper.drawLine(line, true);\r\n } else {\r\n // preprocessor.canvasWrapper.drawLine(line);\r\n svgWrapper.drawLine(line);\r\n }\r\n\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((edge.center || vertexA.isTerminal() && vertexB.isTerminal()) ||\r\n (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1)) {\r\n this.multiplyNormals(normals, opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB),\r\n lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n } else if ((s.sideCount[0] > s.sideCount[1]) ||\r\n (s.totalSideCount[0] > s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((s.sideCount[0] < s.sideCount[1]) ||\r\n (s.totalSideCount[0] <= s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n svgWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else if (edge.wedge === 'down') {\r\n svgWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else {\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n svgWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n svgWrapper = this.svgWrapper;\r\n\r\n var i = graph.vertices.length;\r\n for (var i = 0; i < graph.vertices.length; i++) {\r\n let vertex = graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(graph.vertices);\r\n let isTerminal = opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (opts.atomVisualization === 'allballs') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || graph.vertices.length === 1) {\r\n if (opts.atomVisualization === 'default') {\r\n svgWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (opts.atomVisualization === 'balls') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = graph.vertices[vertex.neighbours[0]].position;\r\n let b = graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n svgWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (opts.debug) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let center = rings[i].center;\r\n svgWrapper.drawDebugPoint(center.x, center.y, 'r: ' + rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.preprocessor.getTotalOverlapScore();\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n return this.preprocessor.getMolecularFormula();\r\n }\r\n\r\n /**\r\n * @param {Array} normals list of normals to multiply\r\n * @param {Number} spacing value to multiply normals by\r\n */\r\n multiplyNormals(normals, spacing) {\r\n normals[0].multiplyScalar(spacing);\r\n normals[1].multiplyScalar(spacing);\r\n }\r\n}\r\n\r\nmodule.exports = SvgDrawer;","const {\r\n getChargeText\r\n} = require('./UtilityFunctions');\r\n\r\nconst Line = require('./Line');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgWrapper {\r\n constructor(themeManager, target, options) {\r\n this.svg = document.getElementById(target);\r\n this.opts = options;\r\n this.gradientId = 0;\r\n\r\n // maintain a list of line elements and their corresponding gradients\r\n // maintain a list of vertex elements\r\n this.paths = [];\r\n this.vertices = [];\r\n this.gradients = [];\r\n\r\n // maintain the offset for drawing purposes\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n // maintain the dimensions\r\n this.drawingWidth = 0;\r\n this.drawingHeight = 0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // for managing color schemes\r\n this.themeManager = themeManager;\r\n\r\n // create the mask\r\n this.maskElements = [];\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\r\n mask.setAttributeNS(null, 'x', 0);\r\n mask.setAttributeNS(null, 'y', 0);\r\n mask.setAttributeNS(null, 'width', '100%');\r\n mask.setAttributeNS(null, 'height', '100%');\r\n mask.setAttributeNS(null, 'fill', 'white');\r\n\r\n this.maskElements.push(mask);\r\n\r\n // clear the svg element\r\n while (this.svg.firstChild) {\r\n this.svg.removeChild(this.svg.firstChild);\r\n }\r\n }\r\n\r\n constructSvg() {\r\n // TODO: add the defs element to put gradients in\r\n let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'),\r\n masks = document.createElementNS('http://www.w3.org/2000/svg', 'mask'),\r\n style = document.createElementNS('http://www.w3.org/2000/svg', 'style'),\r\n paths = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n vertices = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n pathChildNodes = this.paths;\r\n\r\n // give the mask an id\r\n masks.setAttributeNS(null, 'id', 'text-mask');\r\n\r\n // create the css styles\r\n style.appendChild(document.createTextNode(`\r\n .element {\r\n font: ${this.opts.fontSizeLarge}pt Helvetica, Arial, sans-serif;\r\n alignment-baseline: 'middle';\r\n }\r\n .sub {\r\n font: ${this.opts.fontSizeSmall}pt Helvetica, Arial, sans-serif;\r\n }\r\n `));\r\n\r\n for (let path of pathChildNodes) {\r\n paths.appendChild(path);\r\n }\r\n for (let vertex of this.vertices) {\r\n vertices.appendChild(vertex);\r\n }\r\n for (let mask of this.maskElements) {\r\n masks.appendChild(mask);\r\n }\r\n for (let gradient of this.gradients) {\r\n defs.appendChild(gradient);\r\n }\r\n\r\n paths.setAttributeNS(null, 'mask', 'url(#text-mask)');\r\n\r\n if (this.svg) {\r\n this.svg.appendChild(defs);\r\n this.svg.appendChild(masks);\r\n this.svg.appendChild(style);\r\n this.svg.appendChild(paths);\r\n this.svg.appendChild(vertices);\r\n return this.svg;\r\n } else {\r\n let container = document.createElementNS('http://www.w3.org/2000/svg', 'g');\r\n container.appendChild(defs);\r\n container.appendChild(masks);\r\n container.appendChild(style);\r\n container.appendChild(paths);\r\n container.appendChild(vertices);\r\n return container;\r\n }\r\n }\r\n\r\n /**\r\n * Create a linear gradient to apply to a line\r\n *\r\n * @param {Line} line the line to apply the gradiation to.\r\n */\r\n createGradient(line) {\r\n // create the gradient and add it\r\n let gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient'),\r\n gradientUrl = `line-${this.gradientId++}`,\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n gradient.setAttributeNS(null, 'id', gradientUrl);\r\n gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\r\n gradient.setAttributeNS(null, 'x1', fromX);\r\n gradient.setAttributeNS(null, 'y1', fromY);\r\n gradient.setAttributeNS(null, 'x2', toX);\r\n gradient.setAttributeNS(null, 'y2', toY);\r\n\r\n let firstStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n firstStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getLeftElement()) || this.themeManager.getColor('C'));\r\n firstStop.setAttributeNS(null, 'offset', '20%');\r\n\r\n let secondStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n secondStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getRightElement() || this.themeManager.getColor('C')));\r\n secondStop.setAttributeNS(null, 'offset', '100%');\r\n\r\n gradient.appendChild(firstStop);\r\n gradient.appendChild(secondStop);\r\n\r\n this.gradients.push(gradient);\r\n\r\n return gradientUrl;\r\n }\r\n\r\n /**\r\n * Create a tspan element for sub or super scripts that styles the text\r\n * appropriately as one of those text types.\r\n *\r\n * @param {String} text the actual text\r\n * @param {String} shift the type of text, either 'sub', or 'super'\r\n */\r\n createSubSuperScripts(text, shift) {\r\n let elem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n elem.setAttributeNS(null, 'baseline-shift', shift);\r\n elem.appendChild(document.createTextNode(text));\r\n elem.setAttributeNS(null, 'class', 'sub');\r\n\r\n return elem;\r\n }\r\n\r\n /**\r\n * Determine drawing dimensiosn based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n determineDimensions(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n let padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n let scaleX = this.svg.clientWidth / this.drawingWidth;\r\n let scaleY = this.svg.clientHeight / this.drawingHeight;\r\n\r\n let scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n let viewBoxDim = Math.round(this.drawingWidth > this.drawingHeight ? this.drawingWidth : this.drawingHeight);\r\n\r\n this.svg.setAttributeNS(null, 'viewBox', `0 0 ${viewBoxDim} ${viewBoxDim}`);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.svg.clientHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.svg.clientWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Draw an svg ellipse as a ball.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n ball.setAttributeNS(null, 'cx', x + this.offsetX);\r\n ball.setAttributeNS(null, 'cy', y + this.offsetY);\r\n ball.setAttributeNS(null, 'r', this.opts.bondLength / 4.5);\r\n ball.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n\r\n this.vertices.push(ball);\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone(),\r\n normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral(),\r\n start,\r\n end;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n } else {\r\n start = l;\r\n end = r;\r\n }\r\n\r\n let dir = Vector2.subtract(end, start).normalize(),\r\n length = line.getLength(),\r\n step = 1.25 / (length / (this.opts.bondThickness * 3.0)),\r\n changed = false;\r\n\r\n let gradient = this.createGradient(line);\r\n\r\n for (let t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length),\r\n startDash = Vector2.add(start, to),\r\n width = 1.5 * t,\r\n dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n startDash.subtract(dashOffset);\r\n let endDash = startDash.clone();\r\n endDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n\r\n this.drawLine(new Line(startDash, endDash), null, gradient);\r\n }\r\n }\r\n\r\n /**\r\n * Draws a debug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + this.offsetX);\r\n point.setAttributeNS(null, 'cy', y + this.offsetY);\r\n point.setAttributeNS(null, 'r', '2');\r\n point.setAttributeNS(null, 'fill', '#f00');\r\n this.vertices.push(point);\r\n this.drawDebugText(x, y, debugText);\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\r\n textElem.setAttributeNS(null, 'x', x + this.offsetX);\r\n textElem.setAttributeNS(null, 'y', y + this.offsetY);\r\n textElem.setAttributeNS(null, 'class', 'debug');\r\n textElem.setAttributeNS(null, 'fill', '#ff0000');\r\n textElem.setAttributeNS(null, 'style', `\r\n font: 5px Droid Sans, sans-serif;\r\n `);\r\n textElem.appendChild(document.createTextNode(text));\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * Draws a line.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} dashed defaults to false.\r\n * @param {String} gradient gradient url. Defaults to null.\r\n */\r\n drawLine(line, dashed = false, gradient = null) {\r\n let opts = this.opts,\r\n stylesArr = [\r\n ['stroke-linecap', 'round'],\r\n ['stroke-dasharray', dashed ? '5, 5' : 'none'],\r\n ],\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n let styles = stylesArr.map(sub => sub.join(':')).join(';'),\r\n lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line');\r\n\r\n lineElem.setAttributeNS(null, 'x1', fromX);\r\n lineElem.setAttributeNS(null, 'y1', fromY);\r\n lineElem.setAttributeNS(null, 'x2', toX);\r\n lineElem.setAttributeNS(null, 'y2', toY);\r\n lineElem.setAttributeNS(null, 'style', styles);\r\n this.paths.push(lineElem);\r\n\r\n if (gradient == null) {\r\n gradient = this.createGradient(line, fromX, fromY, toX, toY);\r\n }\r\n lineElem.setAttributeNS(null, 'stroke', `url('#${gradient}')`);\r\n }\r\n\r\n /**\r\n * Draw a point.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // first create a mask\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', x + offsetX);\r\n mask.setAttributeNS(null, 'cy', y + offsetY);\r\n mask.setAttributeNS(null, 'r', '1.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // now create the point\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + offsetX);\r\n point.setAttributeNS(null, 'cy', y + offsetY);\r\n point.setAttributeNS(null, 'r', '0.75');\r\n point.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n this.vertices.push(point);\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n pos = {\r\n x: x + offsetX,\r\n y: y + offsetY,\r\n },\r\n textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text'),\r\n writingMode = 'horizontal-tb',\r\n letterSpacing = 'normal',\r\n textOrientation = 'mixed',\r\n textDirection = 'direction: ltr;',\r\n xShift = -2,\r\n yShift = 2.5;\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', pos.x);\r\n mask.setAttributeNS(null, 'cy', pos.y);\r\n mask.setAttributeNS(null, 'r', '3.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // determine writing mode\r\n if (/up|down/.test(direction) && !isTerminal) {\r\n writingMode = 'vertical-rl';\r\n textOrientation = 'upright';\r\n letterSpacing = '-1px';\r\n }\r\n\r\n if (direction === 'down' && !isTerminal) {\r\n xShift = 0;\r\n yShift = -2;\r\n } else if (direction === 'up' && !isTerminal) {\r\n xShift = 0.5;\r\n } else if (direction === 'left') {\r\n xShift = 2;\r\n }\r\n\r\n if (direction === 'left' || (direction === 'up' && !isTerminal)) {\r\n textDirection = 'direction: rtl; unicode-bidi: bidi-override;'\r\n }\r\n\r\n // now the text element\r\n textElem.setAttributeNS(null, 'x', pos.x + xShift);\r\n textElem.setAttributeNS(null, 'y', pos.y + yShift);\r\n textElem.setAttributeNS(null, 'class', 'element');\r\n textElem.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n textElem.setAttributeNS(null, 'style', `\r\n text-anchor: start;\r\n writing-mode: ${writingMode};\r\n text-orientation: ${textOrientation};\r\n letter-spacing: ${letterSpacing};\r\n ${textDirection}\r\n `);\r\n\r\n let textNode = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n // special case for element names that are 2 letters\r\n if (elementName.length > 1) {\r\n let textAnchor = /up|down/.test(direction) ? 'middle' : 'start';\r\n\r\n textNode.setAttributeNS(null, 'style', `\r\n unicode-bidi: plaintext;\r\n writing-mode: lr-tb;\r\n letter-spacing: normal;\r\n text-anchor: ${textAnchor};\r\n `);\r\n }\r\n textNode.appendChild(document.createTextNode(elementName));\r\n textElem.appendChild(textNode);\r\n\r\n // Charge\r\n if (charge) {\r\n let chargeElem = this.createSubSuperScripts(getChargeText(charge), 'super');\r\n textNode.appendChild(chargeElem);\r\n }\r\n\r\n let isotopeText = '0';\r\n\r\n if (isotope > 0) {\r\n let isotopeElem = this.createSubSuperScripts(isotope.toString(), 'super');\r\n textNode.appendChild(isotopeElem);\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') &&\r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = {\r\n '0O': {\r\n element: 'O',\r\n count: 2,\r\n hydrogenCount: 0,\r\n previousElement: 'C',\r\n charge: ''\r\n }\r\n }\r\n charge = 0;\r\n }\r\n\r\n if (hydrogens > 0) {\r\n let hydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n hydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n hydrogenElem.appendChild(document.createTextNode('H'));\r\n textElem.appendChild(hydrogenElem);\r\n\r\n if (hydrogens > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogens, 'sub');\r\n hydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let element = attachedPseudoElement[key].element,\r\n elementCount = attachedPseudoElement[key].count,\r\n hydrogenCount = attachedPseudoElement[key].hydrogenCount,\r\n elementCharge = attachedPseudoElement[key].charge,\r\n pseudoElementElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoElementElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoElementElem.appendChild(document.createTextNode(element));\r\n pseudoElementElem.setAttributeNS(null, 'fill', this.themeManager.getColor(element));\r\n\r\n if (elementCharge !== 0) {\r\n let elementChargeElem = this.createSubSuperScripts(getChargeText(elementCharge), 'super');\r\n pseudoElementElem.appendChild(elementChargeElem);\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n let pseudoHydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoHydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoHydrogenElem.appendChild(document.createTextNode('H'));\r\n pseudoElementElem.appendChild(pseudoHydrogenElem);\r\n\r\n if (hydrogenCount > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogenCount, 'sub');\r\n pseudoHydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n if (elementCount > 1) {\r\n let elementCountElem = this.createSubSuperScripts(elementCount, 'sub');\r\n pseudoElementElem.appendChild(elementCountElem);\r\n }\r\n\r\n textElem.appendChild(pseudoElementElem);\r\n }\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * @param {Line} line the line object to create the wedge from\r\n */\r\n drawWedge(line) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l,\r\n end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness)),\r\n u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness)),\r\n v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness)),\r\n w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n let polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'),\r\n gradient = this.createGradient(line, l.x, l.y, r.x, r.y);\r\n polygon.setAttributeNS(null, 'points', `${t.x},${t.y} ${u.x},${u.y} ${v.x},${v.y} ${w.x},${w.y}`);\r\n polygon.setAttributeNS(null, 'fill', `url('#${gradient}')`);\r\n this.paths.push(polygon);\r\n }\r\n}\r\n\r\nmodule.exports = SvgWrapper;","class ThemeManager {\r\n constructor(colors, theme) {\r\n this.colors = colors;\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n if (key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.theme) {\r\n return this.theme[key];\r\n }\r\n }\r\n\r\n return this.theme['C'];\r\n }\r\n\r\n /**\r\n * Sets the theme to the specified string if it exists. If it does not, this\r\n * does nothing.\r\n *\r\n * @param {String} theme the name of the theme to switch to\r\n */\r\n setTheme(theme) {\r\n if (this.colors.hasOwnProperty(theme)) {\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n // TODO: this probably should notify those who are watching this theme\r\n // manager that the theme has changed so that colors can be changed\r\n // on the fly\r\n }\r\n}\r\n\r\nmodule.exports = ThemeManager;","/**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\nfunction getChargeText(charge) {\r\n console.log('in the utility version of getChargeText');\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n getChargeText,\r\n}","//@ts-check\r\n\r\n/** \r\n * A class representing a 2D vector.\r\n * \r\n * @property {Number} x The x component of the vector.\r\n * @property {Number} y The y component of the vector.\r\n */\r\nclass Vector2 {\r\n /**\r\n * The constructor of the class Vector2.\r\n *\r\n * @param {(Number|Vector2)} x The initial x coordinate value or, if the single argument, a Vector2 object.\r\n * @param {Number} y The initial y coordinate value.\r\n */\r\n constructor(x, y) {\r\n if (arguments.length == 0) {\r\n this.x = 0;\r\n this.y = 0;\r\n } else if (arguments.length == 1) {\r\n this.x = x.x;\r\n this.y = x.y;\r\n } else {\r\n this.x = x;\r\n this.y = y;\r\n }\r\n }\r\n\r\n /**\r\n * Clones this vector and returns the clone.\r\n *\r\n * @returns {Vector2} The clone of this vector.\r\n */\r\n clone() {\r\n return new Vector2(this.x, this.y);\r\n }\r\n\r\n /**\r\n * Returns a string representation of this vector.\r\n *\r\n * @returns {String} A string representation of this vector.\r\n */\r\n toString() {\r\n return '(' + this.x + ',' + this.y + ')';\r\n }\r\n\r\n /**\r\n * Add the x and y coordinate values of a vector to the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n add(vec) {\r\n this.x += vec.x;\r\n this.y += vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Subtract the x and y coordinate values of a vector from the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n subtract(vec) {\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Divide the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n divide(scalar) {\r\n this.x /= scalar;\r\n this.y /= scalar;\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Multiply the x and y coordinate values of this vector by the values of another vector.\r\n *\r\n * @param {Vector2} v A vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiply(v) {\r\n this.x *= v.x;\r\n this.y *= v.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Multiply the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiplyScalar(scalar) {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Inverts this vector. Same as multiply(-1.0).\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n invert() {\r\n this.x = -this.x;\r\n this.y = -this.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vector in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n angle() {\r\n return Math.atan2(this.y, this.x);\r\n }\r\n\r\n /**\r\n * Returns the euclidean distance between this vector and another vector.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Number} The euclidean distance between the two vectors.\r\n */\r\n distance(vec) {\r\n return Math.sqrt((vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y));\r\n }\r\n\r\n /**\r\n * Returns the squared euclidean distance between this vector and another vector. When only the relative distances of a set of vectors are needed, this is is less expensive than using distance(vec).\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} The squared euclidean distance of the two vectors.\r\n */\r\n distanceSq(vec) {\r\n return (vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to the coordinate system.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to the coordinate system.\r\n */\r\n clockwise(vec) {\r\n let a = this.y * vec.x;\r\n let b = this.x * vec.y;\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to an arbitrary third vector.\r\n *\r\n * @param {Vector2} center The central vector.\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to an arbitrary third vector.\r\n */\r\n relativeClockwise(center, vec) {\r\n let a = (this.y - center.y) * (vec.x - center.x);\r\n let b = (this.x - center.x) * (vec.y - center.y);\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Rotates this vector by a given number of radians around the origin of the coordinate system.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotate(angle) {\r\n let tmp = new Vector2(0, 0);\r\n let cosAngle = Math.cos(angle);\r\n let sinAngle = Math.sin(angle);\r\n\r\n tmp.x = this.x * cosAngle - this.y * sinAngle;\r\n tmp.y = this.x * sinAngle + this.y * cosAngle;\r\n \r\n this.x = tmp.x;\r\n this.y = tmp.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this vector around another vector.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @param {Vector2} vec The vector which is used as the rotational center.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateAround(angle, vec) {\r\n let s = Math.sin(angle);\r\n let c = Math.cos(angle);\r\n\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n let x = this.x * c - this.y * s;\r\n let y = this.x * s + this.y * c;\r\n\r\n this.x = x + vec.x;\r\n this.y = y + vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate a vector around a given center to the same angle as another vector (so that the two vectors and the center are in a line, with both vectors on one side of the center), keeps the distance from this vector to the center.\r\n *\r\n * @param {Vector2} vec The vector to rotate this vector to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} [offsetAngle=0.0] An additional amount of radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateTo(vec, center, offsetAngle = 0.0) {\r\n // Problem if this is first position\r\n this.x += 0.001;\r\n this.y -= 0.001;\r\n\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n\r\n this.rotateAround(angle + offsetAngle, center);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates the vector away from a specified vector around a center.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n */\r\n rotateAwayFrom(vec, center, angle) {\r\n this.rotateAround(angle, center);\r\n \r\n let distSqA = this.distanceSq(vec);\r\n \r\n this.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = this.distanceSq(vec);\r\n\r\n // If it was rotated towards the other vertex, rotate in other direction by same amount.\r\n if (distSqB < distSqA) {\r\n this.rotateAround(2.0 * angle, center);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector away from a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateAwayFromAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB < distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector towards a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated towards to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateTowardsAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB > distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the angles between this vector and another vector around a common center of rotation.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @param {Vector2} center The center of rotation.\r\n * @returns {Number} The angle between this vector and another vector around a center of rotation in radians.\r\n */\r\n getRotateToAngle(vec, center) {\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n \r\n return Number.isNaN(angle) ? 0.0 : angle;\r\n }\r\n\r\n /**\r\n * Checks whether a vector lies within a polygon spanned by a set of vectors.\r\n *\r\n * @param {Vector2[]} polygon An array of vectors spanning the polygon.\r\n * @returns {Boolean} A boolean indicating whether or not this vector is within a polygon.\r\n */\r\n isInPolygon(polygon) {\r\n let inside = false;\r\n\r\n // Its not always a given, that the polygon is convex (-> sugars)\r\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\r\n if (((polygon[i].y > this.y) != (polygon[j].y > this.y)) &&\r\n (this.x < (polygon[j].x - polygon[i].x) * (this.y - polygon[i].y) /\r\n (polygon[j].y - polygon[i].y) + polygon[i].x)) {\r\n inside = !inside;\r\n }\r\n }\r\n\r\n\r\n return inside;\r\n }\r\n\r\n /**\r\n * Returns the length of this vector.\r\n *\r\n * @returns {Number} The length of this vector.\r\n */\r\n length() {\r\n return Math.sqrt((this.x * this.x) + (this.y * this.y));\r\n }\r\n\r\n /**\r\n * Returns the square of the length of this vector.\r\n *\r\n * @returns {Number} The square of the length of this vector.\r\n */\r\n lengthSq() {\r\n return (this.x * this.x) + (this.y * this.y);\r\n }\r\n\r\n /**\r\n * Normalizes this vector.\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n normalize() {\r\n this.divide(this.length());\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns a normalized copy of this vector.\r\n *\r\n * @returns {Vector2} A normalized copy of this vector.\r\n */\r\n normalized() {\r\n return Vector2.divideScalar(this, this.length());\r\n }\r\n\r\n /**\r\n * Calculates which side of a line spanned by two vectors this vector is.\r\n *\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} A number indicating the side of this vector, given a line spanned by two other vectors.\r\n */\r\n whichSide(vecA, vecB) {\r\n return (this.x - vecA.x) * (vecB.y - vecA.y) - (this.y - vecA.y) * (vecB.x - vecA.x);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is on the same side of a line spanned by two vectors as another vector.\r\n *\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @param {Vector2} vecC A vector to check whether or not it is on the same side as this vector.\r\n * @returns {Boolean} Returns a boolean indicating whether or not this vector is on the same side as another vector.\r\n */\r\n sameSideAs(vecA, vecB, vecC) {\r\n let d = this.whichSide(vecA, vecB);\r\n let dRef = vecC.whichSide(vecA, vecB);\r\n\r\n return d < 0 && dRef < 0 || d == 0 && dRef == 0 || d > 0 && dRef > 0;\r\n }\r\n\r\n /**\r\n * Adds two vectors and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A summand.\r\n * @param {Vector2} vecB A summand.\r\n * @returns {Vector2} Returns the sum of two vectors.\r\n */\r\n static add(vecA, vecB) {\r\n return new Vector2(vecA.x + vecB.x, vecA.y + vecB.y);\r\n }\r\n\r\n /**\r\n * Subtracts one vector from another and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The minuend.\r\n * @param {Vector2} vecB The subtrahend.\r\n * @returns {Vector2} Returns the difference of two vectors.\r\n */\r\n static subtract(vecA, vecB) {\r\n return new Vector2(vecA.x - vecB.x, vecA.y - vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiply(vecA, vecB) {\r\n return new Vector2(vecA.x * vecB.x, vecA.y * vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vec A vector.\r\n * @param {Number} scalar A scalar.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiplyScalar(vec, scalar) {\r\n return new Vector2(vec.x, vec.y).multiplyScalar(scalar);\r\n }\r\n\r\n /**\r\n * Returns the midpoint of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2} The midpoint of the line spanned by two vectors.\r\n */\r\n static midpoint(vecA, vecB) {\r\n return new Vector2((vecA.x + vecB.x) / 2, (vecA.y + vecB.y) / 2);\r\n }\r\n\r\n /**\r\n * Returns the normals of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two normals, each represented by a vector.\r\n */\r\n static normals(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n new Vector2(-delta.y, delta.x),\r\n new Vector2(delta.y, -delta.x)\r\n ];\r\n }\r\n\r\n /**\r\n * Returns the unit (normalized normal) vectors of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two unit vectors.\r\n */\r\n static units(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n (new Vector2(-delta.y, delta.x)).normalize(),\r\n (new Vector2(delta.y, -delta.x)).normalize()\r\n ];\r\n }\r\n\r\n /**\r\n * Divides a vector by another vector and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Vector2} vecB The divisor.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divide(vecA, vecB) {\r\n return new Vector2(vecA.x / vecB.x, vecA.y / vecB.y);\r\n }\r\n\r\n /**\r\n * Divides a vector by a scalar and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Number} s The scalar.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divideScalar(vecA, s) {\r\n return new Vector2(vecA.x / s, vecA.y / s);\r\n }\r\n\r\n /**\r\n * Returns the dot product of two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The dot product of two vectors.\r\n */\r\n static dot(vecA, vecB) {\r\n return vecA.x * vecB.x + vecA.y * vecB.y;\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The angle between two vectors in radians.\r\n */\r\n static angle(vecA, vecB) {\r\n let dot = Vector2.dot(vecA, vecB);\r\n\r\n return Math.acos(dot / (vecA.length() * vecB.length()));\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors based on a third vector in between.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A (central) vector.\r\n * @param {Vector2} vecC A vector.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static threePointangle(vecA, vecB, vecC) {\r\n let ab = Vector2.subtract(vecB, vecA);\r\n let bc = Vector2.subtract(vecC, vecB);\r\n let abLength = vecA.distance(vecB);\r\n let bcLength = vecB.distance(vecC);\r\n\r\n return Math.acos(Vector2.dot(ab, bc) / (abLength * bcLength));\r\n }\r\n \r\n /**\r\n * Returns the scalar projection of a vector on another vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The vector to be projected.\r\n * @param {Vector2} vecB The vector to be projection upon.\r\n * @returns {Number} The scalar component.\r\n */\r\n static scalarProjection(vecA, vecB) {\r\n let unit = vecB.normalized();\r\n \r\n return Vector2.dot(vecA, unit);\r\n }\r\n\r\n /**\r\n * Returns the average vector (normalized) of the input vectors.\r\n *\r\n * @static\r\n * @param {Array} vecs An array containing vectors.\r\n * @returns {Vector2} The resulting vector (normalized).\r\n */\r\n static averageDirection(vecs) {\r\n let avg = new Vector2(0.0, 0.0);\r\n\r\n for (var i = 0; i < vecs.length; i++) {\r\n let vec = vecs[i];\r\n avg.add(vec);\r\n }\r\n\r\n return avg.normalize();\r\n }\r\n}\r\n\r\nmodule.exports = Vector2;","//@ts-check\r\nconst MathHelper = require('./MathHelper')\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Atom = require('./Atom')\r\nconst VertexState = require('./VertexState')\r\n\r\n/** \r\n * A class representing a vertex.\r\n * \r\n * @property {Number} id The id of this vertex.\r\n * @property {Atom} value The atom associated with this vertex.\r\n * @property {Vector2} position The position of this vertex.\r\n * @property {Vector2} previousPosition The position of the previous vertex.\r\n * @property {Number|null} parentVertexId The id of the previous vertex.\r\n * @property {Number[]} children The ids of the children of this vertex.\r\n * @property {Number[]} spanningTreeChildren The ids of the children of this vertex as defined in the spanning tree defined by the SMILES.\r\n * @property {Number[]} edges The ids of edges associated with this vertex.\r\n * @property {Boolean} positioned A boolean indicating whether or not this vertex has been positioned.\r\n * @property {Number} angle The angle of this vertex.\r\n * @property {Number} dir The direction of this vertex.\r\n * @property {Number} neighbourCount The number of neighbouring vertices.\r\n * @property {Number[]} neighbours The vertex ids of neighbouring vertices.\r\n * @property {String[]} neighbouringElements The element symbols associated with neighbouring vertices.\r\n * @property {Boolean} forcePositioned A boolean indicating whether or not this vertex was positioned using a force-based approach.\r\n * @property {Number} vertexState enum of VertexState for DFS.\r\n */\r\n\r\nclass Vertex {\r\n /**\r\n * The constructor for the class Vertex.\r\n *\r\n * @param {Atom} value The value associated with this vertex.\r\n * @param {Number} [x=0] The initial x coordinate of the positional vector of this vertex.\r\n * @param {Number} [y=0] The initial y coordinate of the positional vector of this vertex.\r\n */\r\n constructor(value, x = 0, y = 0) {\r\n this.id = null;\r\n this.value = value;\r\n this.position = new Vector2(x ? x : 0, y ? y : 0);\r\n this.previousPosition = new Vector2(0, 0);\r\n this.parentVertexId = null;\r\n this.children = Array();\r\n this.spanningTreeChildren = Array();\r\n this.edges = Array();\r\n this.positioned = false;\r\n this.angle = null;\r\n this.dir = 1.0;\r\n this.neighbourCount = 0;\r\n this.neighbours = Array();\r\n this.neighbouringElements = Array();\r\n this.forcePositioned = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n this.component = -1;\r\n this.digits = [];\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex.\r\n * \r\n * @param {Number} x The x component of the coordinates.\r\n * @param {Number} y The y component of the coordinates.\r\n * \r\n */\r\n setPosition(x, y) {\r\n this.position.x = x;\r\n this.position.y = y;\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex from a Vector2.\r\n * \r\n * @param {Vector2} v A 2D vector.\r\n * \r\n */\r\n setPositionFromVector(v) {\r\n this.position.x = v.x;\r\n this.position.y = v.y;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n */\r\n addChild(vertexId) {\r\n this.children.push(vertexId);\r\n this.neighbours.push(vertexId);\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex as the second child of the neighbours array,\r\n * except this vertex is the first vertex of the SMILE string, then it is added as the first.\r\n * This is used to get the correct ordering of neighbours for parity calculations.\r\n * If a hydrogen is implicitly attached to the chiral center, insert as the third child.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n * @param {Number} ringbondIndex The index of the ringbond.\r\n */\r\n addRingbondChild(vertexId, ringbondIndex) {\r\n this.children.push(vertexId);\r\n\r\n if (this.value.bracket) {\r\n let index = 1;\r\n\r\n if (this.id === 0 && this.value.bracket.hcount === 0) {\r\n index = 0;\r\n }\r\n \r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 0) {\r\n index = 2;\r\n }\r\n\r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 2;\r\n } else {\r\n index = 3;\r\n }\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 0) {\r\n index = 1;\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 1;\r\n } else {\r\n index = 2;\r\n }\r\n }\r\n \r\n this.neighbours.splice(index, 0, vertexId);\r\n } else {\r\n this.neighbours.push(vertexId);\r\n }\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Set the vertex id of the parent.\r\n * \r\n * @param {Number} parentVertexId The parents vertex id.\r\n */\r\n setParentVertexId(parentVertexId) {\r\n this.neighbourCount++;\r\n this.parentVertexId = parentVertexId;\r\n this.neighbours.push(parentVertexId);\r\n }\r\n\r\n /**\r\n * Returns true if this vertex is terminal (has no parent or child vertices), otherwise returns false. Always returns true if associated value has property hasAttachedPseudoElements set to true.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not this vertex is terminal.\r\n */\r\n isTerminal() {\r\n if (this.value.hasAttachedPseudoElements) {\r\n return true;\r\n }\r\n\r\n return (this.parentVertexId === null && this.children.length < 2) || this.children.length === 0;\r\n }\r\n\r\n /**\r\n * Clones this vertex and returns the clone.\r\n *\r\n * @returns {Vertex} A clone of this vertex.\r\n */\r\n clone() {\r\n let clone = new Vertex(this.value, this.position.x, this.position.y);\r\n clone.id = this.id;\r\n clone.previousPosition = new Vector2(this.previousPosition.x, this.previousPosition.y);\r\n clone.parentVertexId = this.parentVertexId;\r\n clone.children = ArrayHelper.clone(this.children);\r\n clone.spanningTreeChildren = ArrayHelper.clone(this.spanningTreeChildren);\r\n clone.edges = ArrayHelper.clone(this.edges);\r\n clone.positioned = this.positioned;\r\n clone.angle = this.angle;\r\n clone.forcePositioned = this.forcePositioned;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns true if this vertex and the supplied vertex both have the same id, else returns false.\r\n *\r\n * @param {Vertex} vertex The vertex to check.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices have the same id.\r\n */\r\n equals(vertex) {\r\n return this.id === vertex.id;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vertexes positional vector. If a reference vector is supplied in relations to this vector, else in relations to the coordinate system.\r\n *\r\n * @param {Vector2} [referenceVector=null] - The reference vector.\r\n * @param {Boolean} [returnAsDegrees=false] - If true, returns angle in degrees, else in radians.\r\n * @returns {Number} The angle of this vertex.\r\n */\r\n getAngle(referenceVector = null, returnAsDegrees = false) {\r\n let u = null;\r\n\r\n if (!referenceVector) {\r\n u = Vector2.subtract(this.position, this.previousPosition);\r\n } else {\r\n u = Vector2.subtract(this.position, referenceVector);\r\n }\r\n\r\n if (returnAsDegrees) {\r\n return MathHelper.toDeg(u.angle());\r\n }\r\n\r\n return u.angle();\r\n }\r\n\r\n /**\r\n * Returns the suggested text direction when text is added at the position of this vertex.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @returns {String} The suggested direction of the text.\r\n */\r\n getTextDirection(vertices) {\r\n let neighbours = this.getDrawnNeighbours(vertices);\r\n let angles = Array();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n angles.push(this.getAngle(vertices[neighbours[i]].position));\r\n }\r\n\r\n let textAngle = MathHelper.meanAngle(angles);\r\n\r\n // Round to 0, 90, 180 or 270 degree\r\n let halfPi = Math.PI / 2.0;\r\n textAngle = Math.round(Math.round(textAngle / halfPi) * halfPi);\r\n\r\n if (textAngle === 2) {\r\n return 'down';\r\n } else if (textAngle === -2) {\r\n return 'up';\r\n } else if (textAngle === 0 || textAngle === -0) {\r\n return 'right'; // is checking for -0 necessary?\r\n } else if (textAngle === 3 || textAngle === -3) {\r\n return 'left';\r\n } else {\r\n return 'down'; // default to down\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices.\r\n *\r\n * @param {Number} [vertexId=null] If a value is supplied, the vertex with this id is excluded from the returned indices.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices.\r\n */\r\n getNeighbours(vertexId = null) {\r\n if (vertexId === null) {\r\n return this.neighbours.slice();\r\n }\r\n\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (this.neighbours[i] !== vertexId) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices that will be drawn (vertex.value.isDrawn === true).\r\n * \r\n * @param {Vertex[]} vertices An array containing the vertices associated with the current molecule.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices that will be drawn.\r\n */\r\n getDrawnNeighbours(vertices) {\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (vertices[this.neighbours[i]].value.isDrawn) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns the number of neighbours of this vertex.\r\n *\r\n * @returns {Number} The number of neighbours.\r\n */\r\n getNeighbourCount() {\r\n return this.neighbourCount;\r\n }\r\n\r\n /**\r\n * Returns a list of ids of vertices neighbouring this one in the original spanning tree, excluding the ringbond connections.\r\n *\r\n * @param {Number} [vertexId=null] If supplied, the vertex with this id is excluded from the array returned.\r\n * @returns {Number[]} An array containing the ids of the neighbouring vertices.\r\n */\r\n getSpanningTreeNeighbours(vertexId = null) {\r\n let neighbours = Array();\r\n\r\n for (let i = 0; i < this.spanningTreeChildren.length; i++) {\r\n if (vertexId === undefined || vertexId != this.spanningTreeChildren[i]) {\r\n neighbours.push(this.spanningTreeChildren[i]);\r\n }\r\n }\r\n\r\n if (this.parentVertexId != null) {\r\n if (vertexId === undefined || vertexId != this.parentVertexId) {\r\n neighbours.push(this.parentVertexId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Gets the next vertex in the ring in opposide direction to the supplied vertex id.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @param {Number} ringId The id of the ring containing this vertex.\r\n * @param {Number} previousVertexId The id of the previous vertex. The next vertex will be opposite from the vertex with this id as seen from this vertex.\r\n * @returns {Number} The id of the next vertex in the ring.\r\n */\r\n getNextInRing(vertices, ringId, previousVertexId) {\r\n let neighbours = this.getNeighbours();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (ArrayHelper.contains(vertices[neighbours[i]].value.rings, {\r\n value: ringId\r\n }) &&\r\n neighbours[i] != previousVertexId) {\r\n return neighbours[i];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n\r\nmodule.exports = Vertex;","//@ts-check\r\n\r\nclass VertexState {\r\n\r\n /**\r\n * Enum values of Vertex State for DFS\r\n * @return {{NOT_FOUND: number, OPEN: number, CLOSED: number, FULLY_CLOSED: number}}\r\n */\r\n static get VALUES() {\r\n return { NOT_FOUND: 0, OPEN: 1, CLOSED: 2, FULLY_CLOSED: 3 };\r\n }\r\n}\r\n\r\nmodule.exports = VertexState;\r\n"]} \ No newline at end of file +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","app.js","src/ArrayHelper.js","src/Atom.js","src/CanvasWrapper.js","src/DecayPoint.js","src/DecayState.js","src/Direction.js","src/Drawer.js","src/Edge.js","src/Graph.js","src/Line.js","src/MathHelper.js","src/MutableBoolean.js","src/MutableCounter.js","src/Neighbour.js","src/Node.js","src/Parser.js","src/Ring.js","src/RingConnection.js","src/SSSR.js","src/SequenceType.js","src/SmallGraph.js","src/SvgDrawer.js","src/SvgWrapper.js","src/ThemeManager.js","src/UtilityFunctions.js","src/Vector2.js","src/Vertex.js","src/VertexState.js"],"names":[],"mappings":"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","file":"smiles-drawer.min.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i {\r\n const context = canvas.getContext('2d');\r\n context.clearRect(0, 0, canvas.width, canvas.height);\r\n })\r\n};\r\n\r\n/**\r\n* Parses the entered smiles string.\r\n*\r\n* @static\r\n* @param {String} smiles A SMILES string.\r\n* @param {Function} successCallback A callback that is called on success with the parse tree.\r\n* @param {Function} errorCallback A callback that is called with the error object on error.\r\n*/\r\nSmilesDrawer.parse = function(smiles, successCallback, errorCallback) {\r\n try {\r\n if (successCallback) {\r\n successCallback(Parser.parse(smiles));\r\n }\r\n } catch (err) {\r\n if (errorCallback) {\r\n errorCallback(err);\r\n }\r\n }\r\n};\r\n\r\nif (canUseDOM) {\r\n window.SmilesDrawer = SmilesDrawer;\r\n}\r\n\r\n// There be dragons (polyfills)\r\n\r\nif (!Array.prototype.fill) {\r\nObject.defineProperty(Array.prototype, 'fill', {\r\n value: function(value) {\r\n\r\n // Steps 1-2.\r\n if (this == null) {\r\n throw new TypeError('this is null or not defined');\r\n }\r\n\r\n var O = Object(this);\r\n\r\n // Steps 3-5.\r\n var len = O.length >>> 0;\r\n\r\n // Steps 6-7.\r\n var start = arguments[1];\r\n var relativeStart = start >> 0;\r\n\r\n // Step 8.\r\n var k = relativeStart < 0 ?\r\n Math.max(len + relativeStart, 0) :\r\n Math.min(relativeStart, len);\r\n\r\n // Steps 9-10.\r\n var end = arguments[2];\r\n var relativeEnd = end === undefined ?\r\n len : end >> 0;\r\n\r\n // Step 11.\r\n var final = relativeEnd < 0 ?\r\n Math.max(len + relativeEnd, 0) :\r\n Math.min(relativeEnd, len);\r\n\r\n // Step 12.\r\n while (k < final) {\r\n O[k] = value;\r\n k++;\r\n }\r\n\r\n // Step 13.\r\n return O;\r\n }\r\n});\r\n}\r\n\r\nmodule.exports = SmilesDrawer;","//@ts-check\r\n\r\n/** \r\n * A static class containing helper functions for array-related tasks. \r\n */\r\nclass ArrayHelper {\r\n /**\r\n * Clone an array or an object. If an object is passed, a shallow clone will be created.\r\n *\r\n * @static\r\n * @param {*} arr The array or object to be cloned.\r\n * @returns {*} A clone of the array or object.\r\n */\r\n static clone(arr) {\r\n let out = Array.isArray(arr) ? Array() : {};\r\n \r\n for (let key in arr) {\r\n let value = arr[key];\r\n \r\n if (typeof value.clone === 'function') {\r\n out[key] = value.clone();\r\n }\r\n else {\r\n out[key] = (typeof value === 'object') ? ArrayHelper.clone(value) : value;\r\n }\r\n }\r\n \r\n return out;\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not the two arrays contain the same elements.\r\n * Only supports 1d, non-nested arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not the two arrays contain the same elements.\r\n */\r\n static equals(arrA, arrB) {\r\n if (arrA.length !== arrB.length) {\r\n return false;\r\n }\r\n\r\n let tmpA = arrA.slice().sort();\r\n let tmpB = arrB.slice().sort();\r\n\r\n for (let i = 0; i < tmpA.length; i++) {\r\n if (tmpA[i] !== tmpB[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns a string representation of an array. If the array contains objects with an id property, the id property is printed for each of the elements.\r\n *\r\n * @static\r\n * @param {Object[]} arr An array.\r\n * @param {*} arr[].id If the array contains an object with the property 'id', the properties value is printed. Else, the array elements value is printend.\r\n * @returns {String} A string representation of the array.\r\n */\r\n static print(arr) {\r\n if (arr.length == 0) {\r\n return '';\r\n }\r\n\r\n let s = '(';\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n s += arr[i].id ? arr[i].id + ', ' : arr[i] + ', ';\r\n }\r\n\r\n s = s.substring(0, s.length - 2);\r\n\r\n return s + ')';\r\n }\r\n\r\n /**\r\n * Run a function for each element in the array. The element is supplied as an argument for the callback function\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Function} callback The callback function that is called for each element.\r\n */\r\n static each(arr, callback) {\r\n for (let i = 0; i < arr.length; i++) {\r\n callback(arr[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Return the array element from an array containing objects, where a property of the object is set to a given value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {(String|Number)} property A property contained within an object in the array.\r\n * @param {(String|Number)} value The value of the property.\r\n * @returns {*} The array element matching the value.\r\n */\r\n static get(arr, property, value) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][property] == value) {\r\n return arr[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains a given value. the options object passed as a second argument can contain three properties. value: The value to be searched for. property: The property that is to be searched for a given value. func: A function that is used as a callback to return either true or false in order to do a custom comparison.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Object} options See method description.\r\n * @param {*} options.value The value for which to check.\r\n * @param {String} [options.property=undefined] The property on which to check.\r\n * @param {Function} [options.func=undefined] A custom property function.\r\n * @returns {Boolean} A boolean whether or not the array contains a value.\r\n */\r\n static contains(arr, options) {\r\n if (!options.property && !options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] == options.value) {\r\n return true;\r\n }\r\n }\r\n } else if (options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (options.func(arr[i])) {\r\n return true;\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][options.property] == options.value) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array containing the intersection between two arrays. That is, values that are common to both arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The intersecting vlaues.\r\n */\r\n static intersection(arrA, arrB) {\r\n let intersection = [];\r\n \r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n intersection.push(arrA[i]);\r\n }\r\n }\r\n }\r\n\r\n return intersection;\r\n }\r\n\r\n /**\r\n * Returns an array of unique elements contained in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @returns {Array} An array of unique elements contained within the array supplied as an argument.\r\n */\r\n static unique(arr) {\r\n let contains = {};\r\n return arr.filter(function (i) {\r\n // using !== instead of hasOwnProperty (http://andrew.hedges.name/experiments/in/)\r\n return contains[i] !== undefined ? false : (contains[i] = true);\r\n });\r\n }\r\n\r\n /**\r\n * Count the number of occurences of a value in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be counted.\r\n * @returns {Number} The number of occurences of a value in the array.\r\n */\r\n static count(arr, value) {\r\n let count = 0;\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] === value) {\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Toggles the value of an array. If a value is not contained in an array, the array returned will contain all the values of the original array including the value. If a value is contained in an array, the array returned will contain all the values of the original array excluding the value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be toggled.\r\n * @returns {Array} The toggled array.\r\n */\r\n static toggle(arr, value) {\r\n let newArr = Array();\r\n\r\n let removed = false;\r\n for (let i = 0; i < arr.length; i++) {\r\n // Do not copy value if it exists\r\n if (arr[i] !== value) {\r\n newArr.push(arr[i]);\r\n } else {\r\n // The element was not copied to the new array, which\r\n // means it was removed\r\n removed = true;\r\n }\r\n }\r\n\r\n // If the element was not removed, then it was not in the array\r\n // so add it\r\n if (!removed) {\r\n newArr.push(value);\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n /**\r\n * Remove a value from an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} A new array with the element with a given value removed.\r\n */\r\n static remove(arr, value) {\r\n let tmp = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] !== value) {\r\n tmp.push(arr[i]);\r\n }\r\n }\r\n\r\n return tmp;\r\n }\r\n\r\n /**\r\n * Remove a value from an array with unique values.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} An array with the element with a given value removed.\r\n */\r\n static removeUnique(arr, value) {\r\n let index = arr.indexOf(value);\r\n\r\n if (index > -1) {\r\n arr.splice(index, 1);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Remove all elements contained in one array from another array.\r\n *\r\n * @static\r\n * @param {Array} arrA The array to be filtered.\r\n * @param {Array} arrB The array containing elements that will be removed from the other array.\r\n * @returns {Array} The filtered array.\r\n */\r\n static removeAll(arrA, arrB) {\r\n return arrA.filter(function (item) {\r\n return arrB.indexOf(item) === -1;\r\n });\r\n }\r\n\r\n /**\r\n * Merges two arrays and returns the result. The first array will be appended to the second array.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The merged array.\r\n */\r\n static merge(arrA, arrB) {\r\n let arr = new Array(arrA.length + arrB.length);\r\n\r\n for (let i = 0; i < arrA.length; i++) {\r\n arr[i] = arrA[i];\r\n }\r\n\r\n for (let i = 0; i < arrB.length; i++) {\r\n arr[arrA.length + i] = arrB[i];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains all the elements of another array, without regard to the order.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not both array contain the same elements.\r\n */\r\n static containsAll(arrA, arrB) {\r\n let containing = 0;\r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n containing++;\r\n }\r\n }\r\n }\r\n\r\n return containing === arrB.length;\r\n }\r\n \r\n /**\r\n * Sort an array of atomic number information. Where the number is indicated as x, x.y, x.y.z, ...\r\n *\r\n * @param {Object[]} arr An array of vertex ids with their associated atomic numbers.\r\n * @param {Number} arr[].vertexId A vertex id.\r\n * @param {String} arr[].atomicNumber The atomic number associated with the vertex id.\r\n * @returns {Object[]} The array sorted by atomic number. Example of an array entry: { atomicNumber: 2, vertexId: 5 }.\r\n */\r\n static sortByAtomicNumberDesc(arr) {\r\n let map = arr.map(function(e, i) {\r\n return { index: i, value: e.atomicNumber.split('.').map(Number) };\r\n });\r\n\r\n map.sort(function(a, b) {\r\n let min = Math.min(b.value.length, a.value.length);\r\n let i = 0;\r\n \r\n while(i < min && b.value[i] === a.value[i]) {\r\n i++;\r\n }\r\n\r\n return i === min ? b.value.length - a.value.length : b.value[i] - a.value[i];\r\n });\r\n\r\n return map.map(function(e) {\r\n return arr[e.index];\r\n });\r\n }\r\n\r\n /**\r\n * Copies a an n-dimensional array.\r\n * \r\n * @param {Array} arr The array to be copied.\r\n * @returns {Array} The copy.\r\n */\r\n static deepCopy(arr) {\r\n let newArr = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n let item = arr[i];\r\n\r\n if (item instanceof Array) {\r\n newArr[i] = ArrayHelper.deepCopy(item);\r\n } else {\r\n newArr[i] = item;\r\n }\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = ArrayHelper;","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper');\r\n\r\n/** \r\n * A class representing an atom.\r\n * \r\n * @property {String} element The element symbol of this atom. Single-letter symbols are always uppercase. Examples: H, C, F, Br, Si, ...\r\n * @property {Boolean} drawExplicit A boolean indicating whether or not this atom is drawn explicitly (for example, a carbon atom). This overrides the default behaviour.\r\n * @property {Object[]} ringbonds An array containing the ringbond ids and bond types as specified in the original SMILE.\r\n * @property {String} branchBond The branch bond as defined in the SMILES.\r\n * @property {Number} ringbonds[].id The ringbond id as defined in the SMILES.\r\n * @property {String} ringbonds[].bondType The bond type of the ringbond as defined in the SMILES.\r\n * @property {Number[]} rings The ids of rings which contain this atom.\r\n * @property {String} bondType The bond type associated with this array. Examples: -, =, #, ...\r\n * @property {Boolean} isBridge A boolean indicating whether or not this atom is part of a bridge in a bridged ring (contained by the largest ring).\r\n * @property {Boolean} isBridgeNode A boolean indicating whether or not this atom is a bridge node (a member of the largest ring in a bridged ring which is connected to a bridge-atom).\r\n * @property {Number[]} originalRings Used to back up rings when they are replaced by a bridged ring.\r\n * @property {Number} bridgedRing The id of the bridged ring if the atom is part of a bridged ring.\r\n * @property {Number[]} anchoredRings The ids of the rings that are anchored to this atom. The centers of anchored rings are translated when this atom is translated.\r\n * @property {Object} bracket If this atom is defined as a bracket atom in the original SMILES, this object contains all the bracket information. Example: { hcount: {Number}, charge: ['--', '-', '+', '++'], isotope: {Number} }.\r\n * @property {Number} plane Specifies on which \"plane\" the atoms is in stereochemical deptictions (-1 back, 0 middle, 1 front).\r\n * @property {Object[]} attachedPseudoElements A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @property {String} attachedPseudoElement[].element The element symbol.\r\n * @property {Number} attachedPseudoElement[].count The number of occurences that match the key.\r\n * @property {Number} attachedPseudoElement[].hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n * @property {Boolean} hasAttachedPseudoElements A boolean indicating whether or not this attom will be drawn with an attached pseudo element or concatinated elements.\r\n * @property {Boolean} isDrawn A boolean indicating whether or not this atom is drawn. In contrast to drawExplicit, the bond is drawn neither.\r\n * @property {Boolean} isConnectedToRing A boolean indicating whether or not this atom is directly connected (but not a member of) a ring.\r\n * @property {String[]} neighbouringElements An array containing the element symbols of neighbouring atoms.\r\n * @property {Boolean} isPartOfAromaticRing A boolean indicating whether or not this atom is part of an explicitly defined aromatic ring. Example: c1ccccc1.\r\n * @property {Number} bondCount The number of bonds in which this atom is participating.\r\n * @property {String} chirality The chirality of this atom if it is a stereocenter (R or S).\r\n * @property {Number} priority The priority of this atom acording to the CIP rules, where 0 is the highest priority.\r\n * @property {Boolean} mainChain A boolean indicating whether or not this atom is part of the main chain (used for chirality).\r\n * @property {String} hydrogenDirection The direction of the hydrogen, either up or down. Only for stereocenters with and explicit hydrogen.\r\n * @property {Number} subtreeDepth The depth of the subtree coming from a stereocenter.\r\n */\r\nclass Atom {\r\n /**\r\n * The constructor of the class Atom.\r\n *\r\n * @param {String} element The one-letter code of the element.\r\n * @param {String} [bondType='-'] The type of the bond associated with this atom.\r\n */\r\n constructor(element, bondType = '-') {\r\n this.element = element.length === 1 ? element.toUpperCase() : element;\r\n this.drawExplicit = false;\r\n this.ringbonds = Array();\r\n this.rings = Array();\r\n this.bondType = bondType;\r\n this.branchBond = null;\r\n this.isBridge = false;\r\n this.isBridgeNode = false;\r\n this.originalRings = Array();\r\n this.bridgedRing = null;\r\n this.anchoredRings = Array();\r\n this.bracket = null;\r\n this.plane = 0;\r\n this.attachedPseudoElements = {};\r\n this.hasAttachedPseudoElements = false;\r\n this.isDrawn = true;\r\n this.isConnectedToRing = false;\r\n this.neighbouringElements = Array();\r\n this.isPartOfAromaticRing = element !== this.element;\r\n this.bondCount = 0;\r\n this.chirality = '';\r\n this.isStereoCenter = false;\r\n this.priority = 0;\r\n this.mainChain = false;\r\n this.hydrogenDirection = 'down';\r\n this.subtreeDepth = 1;\r\n this.hasHydrogen = false;\r\n }\r\n\r\n /**\r\n * Adds a neighbouring element to this atom.\r\n * \r\n * @param {String} element A string representing an element.\r\n */\r\n addNeighbouringElement(element) {\r\n this.neighbouringElements.push(element);\r\n }\r\n\r\n /**\r\n * Attaches a pseudo element (e.g. Ac) to the atom.\r\n * @param {String} element The element identifier (e.g. Br, C, ...).\r\n * @param {String} previousElement The element that is part of the main chain (not the terminals that are converted to the pseudo element or concatinated).\r\n * @param {Number} [hydrogenCount=0] The number of hydrogens for the element.\r\n * @param {Number} [charge=0] The charge for the element.\r\n */\r\n attachPseudoElement(element, previousElement, hydrogenCount = 0, charge = 0) {\r\n if (hydrogenCount === null) {\r\n hydrogenCount = 0;\r\n }\r\n\r\n if (charge === null) {\r\n charge = 0;\r\n }\r\n\r\n let key = hydrogenCount + element + charge;\r\n\r\n if (this.attachedPseudoElements[key]) {\r\n this.attachedPseudoElements[key].count += 1;\r\n } else {\r\n this.attachedPseudoElements[key] = {\r\n element: element,\r\n count: 1,\r\n hydrogenCount: hydrogenCount,\r\n previousElement: previousElement,\r\n charge: charge\r\n };\r\n }\r\n\r\n this.hasAttachedPseudoElements = true;\r\n }\r\n\r\n /**\r\n * Returns the attached pseudo elements sorted by hydrogen count (ascending).\r\n *\r\n * @returns {Object} The sorted attached pseudo elements.\r\n */\r\n getAttachedPseudoElements() {\r\n let ordered = {};\r\n let that = this;\r\n\r\n Object.keys(this.attachedPseudoElements).sort().forEach(function (key) {\r\n ordered[key] = that.attachedPseudoElements[key];\r\n });\r\n\r\n return ordered;\r\n }\r\n\r\n /**\r\n * Returns the number of attached pseudo elements.\r\n *\r\n * @returns {Number} The number of attached pseudo elements.\r\n */\r\n getAttachedPseudoElementsCount() {\r\n return Object.keys(this.attachedPseudoElements).length;\r\n }\r\n\r\n /**\r\n * Returns whether this atom is a heteroatom (not C and not H).\r\n *\r\n * @returns {Boolean} A boolean indicating whether this atom is a heteroatom.\r\n */\r\n isHeteroAtom() {\r\n return this.element !== 'C' && this.element !== 'H';\r\n }\r\n\r\n /**\r\n * Defines this atom as the anchor for a ring. When doing repositionings of the vertices and the vertex associated with this atom is moved, the center of this ring is moved as well.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n addAnchoredRing(ringId) {\r\n if (!ArrayHelper.contains(this.anchoredRings, {\r\n value: ringId\r\n })) {\r\n this.anchoredRings.push(ringId);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of ringbonds (breaks in rings to generate the MST of the smiles) within this atom is connected to.\r\n *\r\n * @returns {Number} The number of ringbonds this atom is connected to.\r\n */\r\n getRingbondCount() {\r\n return this.ringbonds.length;\r\n }\r\n\r\n /**\r\n * Backs up the current rings.\r\n */\r\n backupRings() {\r\n this.originalRings = Array(this.rings.length);\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings[i] = this.rings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recent backed up rings.\r\n */\r\n restoreRings() {\r\n this.rings = Array(this.originalRings.length);\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings[i] = this.originalRings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not two atoms share a common ringbond id. A ringbond is a break in a ring created when generating the spanning tree of a structure.\r\n *\r\n * @param {Atom} atomA An atom.\r\n * @param {Atom} atomB An atom.\r\n * @returns {Boolean} A boolean indicating whether or not two atoms share a common ringbond.\r\n */\r\n haveCommonRingbond(atomA, atomB) {\r\n for (let i = 0; i < atomA.ringbonds.length; i++) {\r\n for (let j = 0; j < atomB.ringbonds.length; j++) {\r\n if (atomA.ringbonds[i].id == atomB.ringbonds[j].id) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not the neighbouring elements of this atom equal the supplied array.\r\n * \r\n * @param {String[]} arr An array containing all the elements that are neighbouring this atom. E.g. ['C', 'O', 'O', 'N']\r\n * @returns {Boolean} A boolean indicating whether or not the neighbours match the supplied array of elements.\r\n */\r\n neighbouringElementsEqual(arr) {\r\n if (arr.length !== this.neighbouringElements.length) {\r\n return false;\r\n }\r\n\r\n arr.sort();\r\n this.neighbouringElements.sort();\r\n\r\n for (var i = 0; i < this.neighbouringElements.length; i++) {\r\n if (arr[i] !== this.neighbouringElements[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the atomic number of this atom.\r\n * \r\n * @returns {Number} The atomic number of this atom.\r\n */\r\n getAtomicNumber() {\r\n return Atom.atomicNumbers[this.element];\r\n }\r\n\r\n /**\r\n * Get the maximum number of bonds for this atom.\r\n * \r\n * @returns {Number} The maximum number of bonds of this atom.\r\n */\r\n getMaxBonds() {\r\n return Atom.maxBonds[this.element];\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to their maximum bonds.\r\n */\r\n static get maxBonds() {\r\n return {\r\n 'H': 1,\r\n 'C': 4,\r\n 'N': 3,\r\n 'O': 2,\r\n 'P': 3,\r\n 'S': 2,\r\n 'B': 3,\r\n 'F': 1,\r\n 'I': 1,\r\n 'Cl': 1,\r\n 'Br': 1\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic number.\r\n */\r\n static get atomicNumbers() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic mass.\r\n */\r\n static get mass() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n}\r\n\r\nmodule.exports = Atom;","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Ring = require('./Ring');\r\nconst { getChargeText } = require('./UtilityFunctions');\r\n\r\n/** \r\n * A class wrapping a canvas element.\r\n * \r\n * @property {HTMLElement} canvas The HTML element for the canvas associated with this CanvasWrapper instance.\r\n * @property {CanvasRenderingContext2D} ctx The CanvasRenderingContext2D of the canvas associated with this CanvasWrapper instance.\r\n * @property {Object} colors The colors object as defined in the SmilesDrawer options.\r\n * @property {Object} opts The SmilesDrawer options.\r\n * @property {Number} drawingWidth The width of the canvas.\r\n * @property {Number} drawingHeight The height of the canvas.\r\n * @property {Number} realWidth The width of the canvas real.\r\n * @property {Number} realHeight The height of the canvas real.\r\n * @property {Number} offsetX The horizontal offset required for centering the drawing.\r\n * @property {Number} offsetY The vertical offset required for centering the drawing.\r\n * @property {Number} fontLarge The large font size in pt.\r\n * @property {Number} fontSmall The small font size in pt.\r\n */\r\nclass CanvasWrapper {\r\n /**\r\n * The constructor for the class CanvasWrapper.\r\n *\r\n * @param {(String|HTMLElement)} target The canvas id or the canvas HTMLElement.\r\n * @param {ThemeManager} themeManager Theme manager for setting proper colors.\r\n * @param {Object} options The smiles drawer options object.\r\n */\r\n constructor(target, themeManager, options) {\r\n if (typeof target === 'string' || target instanceof String) {\r\n this.canvas = document.getElementById(target);\r\n } else {\r\n this.canvas = target;\r\n }\r\n\r\n this.ctx = this.canvas.getContext('2d');\r\n this.themeManager = themeManager;\r\n this.opts = options;\r\n this.drawingWidth = 0.0;\r\n this.drawingHeight = 0.0;\r\n this.realWidth = 0.0;\r\n this.realHeight = 0.0;\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n this.fontLarge = this.opts.fontSizeLarge + 'pt Helvetica, Arial, sans-serif';\r\n this.fontSmall = this.opts.fontSizeSmall + 'pt Helvetica, Arial, sans-serif';\r\n\r\n this.updateSize(this.opts.width, this.opts.height);\r\n\r\n this.ctx.font = this.fontLarge;\r\n this.hydrogenWidth = this.ctx.measureText('H').width;\r\n this.halfHydrogenWidth = this.hydrogenWidth / 2.0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // TODO: Find out why clear was here.\r\n // this.clear();\r\n }\r\n\r\n /**\r\n * Update the width and height of the canvas\r\n * \r\n * @param {Number} width \r\n * @param {Number} height \r\n */\r\n updateSize(width, height) {\r\n this.devicePixelRatio = window.devicePixelRatio || 1;\r\n this.backingStoreRatio = this.ctx.webkitBackingStorePixelRatio || this.ctx.mozBackingStorePixelRatio ||\r\n this.ctx.msBackingStorePixelRatio || this.ctx.oBackingStorePixelRatio ||\r\n this.ctx.backingStorePixelRatio || 1;\r\n this.ratio = this.devicePixelRatio / this.backingStoreRatio;\r\n\r\n this.canvas.width = width * this.ratio;\r\n this.canvas.height = height * this.ratio;\r\n if (this.ratio !== 1) {\r\n this.realWidth = width;\r\n this.realHeight = height;\r\n this.canvas.style.width = width + 'px';\r\n this.canvas.style.height = height + 'px';\r\n this.ctx.setTransform(this.ratio, 0, 0, this.ratio, 0, 0);\r\n }\r\n }\r\n\r\n /**\r\n * Sets a provided theme.\r\n *\r\n * @param {Object} theme A theme from the smiles drawer options.\r\n */\r\n setTheme(theme) {\r\n this.colors = theme;\r\n }\r\n\r\n /**\r\n * Scale the canvas based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n scale(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n var padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n var scaleX = this.canvas.offsetWidth / this.drawingWidth;\r\n var scaleY = this.canvas.offsetHeight / this.drawingHeight;\r\n\r\n var scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n\r\n this.ctx.scale(scale, scale);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.canvas.offsetHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.canvas.offsetWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Resets the transform of the canvas.\r\n */\r\n reset() {\r\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.colors) {\r\n return this.colors[key];\r\n }\r\n\r\n return this.colors['C'];\r\n }\r\n\r\n /**\r\n * Draws a circle to a canvas context.\r\n * @param {Number} x The x coordinate of the circles center.\r\n * @param {Number} y The y coordinate of the circles center.\r\n * @param {Number} radius The radius of the circle\r\n * @param {String} color A hex encoded color.\r\n * @param {Boolean} [fill=true] Whether to fill or stroke the circle.\r\n * @param {Boolean} [debug=false] Draw in debug mode.\r\n * @param {String} [debugText=''] A debug message.\r\n */\r\n drawCircle(x, y, radius, color, fill = true, debug = false, debugText = '') {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.lineWidth = 1.5;\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, radius, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n\r\n if (debug) {\r\n if (fill) {\r\n ctx.fillStyle = '#f00';\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = '#f00';\r\n ctx.stroke();\r\n }\r\n\r\n this.drawDebugText(x, y, debugText);\r\n } else {\r\n if (fill) {\r\n ctx.fillStyle = color;\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = color;\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a line to a canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} [dashed=false] Whether or not the line is dashed.\r\n * @param {Number} [alpha=1.0] The alpha value of the color.\r\n */\r\n drawLine(line, dashed = false, alpha = 1.0) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(4.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n // Draw the \"shadow\"\r\n if (!dashed) {\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness + 1.2;\r\n ctx.strokeStyle = this.themeManager.getColor('BACKGROUND');\r\n ctx.stroke();\r\n ctx.globalCompositeOperation = 'source-over';\r\n ctx.restore();\r\n }\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n\r\n let gradient = this.ctx.createLinearGradient(l.x, l.y, r.x, r.y);\r\n if (line.isDecayPoint) {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(\"DECAY\"));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(\"DECAY\"));\r\n } else {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n }\r\n\r\n if (dashed) {\r\n ctx.setLineDash([1, 1.5]);\r\n ctx.lineWidth = this.opts.bondThickness / 1.5;\r\n }\r\n\r\n if (alpha < 1.0) {\r\n ctx.globalAlpha = alpha;\r\n }\r\n\r\n ctx.strokeStyle = gradient;\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Number} width The wedge width.\r\n */\r\n drawWedge(line, width = 1.0) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(5.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l;\r\n let end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness));\r\n let u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness));\r\n let v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness));\r\n let w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(t.x, t.y);\r\n ctx.lineTo(u.x, u.y);\r\n ctx.lineTo(v.x, v.y);\r\n ctx.lineTo(w.x, w.y);\r\n\r\n let gradient = this.ctx.createRadialGradient(r.x, r.y, this.opts.bondLength, r.x, r.y, 0);\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n let l = line.getLeftVector().clone();\r\n let r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start;\r\n let end;\r\n let sStart;\r\n let sEnd;\r\n\r\n let shortLine = line.clone();\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n\r\n shortLine.shortenRight(1.0);\r\n\r\n sStart = shortLine.getRightVector().clone();\r\n sEnd = shortLine.getLeftVector().clone();\r\n } else {\r\n start = l;\r\n end = r;\r\n\r\n shortLine.shortenLeft(1.0);\r\n\r\n sStart = shortLine.getLeftVector().clone();\r\n sEnd = shortLine.getRightVector().clone();\r\n }\r\n\r\n sStart.x += offsetX;\r\n sStart.y += offsetY;\r\n sEnd.x += offsetX;\r\n sEnd.y += offsetY;\r\n\r\n let dir = Vector2.subtract(end, start).normalize();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n let length = line.getLength();\r\n let step = 1.25 / (length / (this.opts.bondThickness * 3.0));\r\n\r\n let changed = false;\r\n for (var t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length);\r\n let startDash = Vector2.add(start, to);\r\n let width = 1.5 * t;\r\n let dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n if (!changed && t > 0.5) {\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.strokeStyle = this.themeManager.getColor(line.getRightElement()) || this.themeManager.getColor('C');\r\n changed = true;\r\n }\r\n \r\n startDash.subtract(dashOffset);\r\n ctx.moveTo(startDash.x, startDash.y);\r\n startDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n ctx.lineTo(startDash.x, startDash.y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.font = '5px Droid Sans, sans-serif';\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'top';\r\n ctx.fillStyle = '#ff0000';\r\n ctx.fillText(text, x + this.offsetX, y + this.offsetY);\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a ball to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, this.opts.bondLength / 4.5, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a point to the canvas.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, 1.5, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, 0.75, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'alphabetic';\r\n\r\n // Charge\r\n let chargeText = '';\r\n let chargeWidth = 0;\r\n\r\n if (charge) {\r\n chargeText = getChargeText(charge);\r\n\r\n ctx.font = this.fontSmall;\r\n chargeWidth = ctx.measureText(chargeText).width;\r\n }\r\n\r\n let isotopeText = '0';\r\n let isotopeWidth = 0;\r\n\r\n if (isotope > 0) {\r\n isotopeText = isotope.toString();\r\n ctx.font = this.fontSmall;\r\n isotopeWidth = ctx.measureText(isotopeText).width;\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') && \r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = { '0O': { element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: '' } };\r\n charge = 0;\r\n }\r\n\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillStyle = this.themeManager.getColor('BACKGROUND');\r\n\r\n let dim = ctx.measureText(elementName);\r\n\r\n dim.totalWidth = dim.width + chargeWidth;\r\n dim.height = parseInt(this.fontLarge, 10);\r\n\r\n let r = (dim.width > this.opts.fontSizeLarge) ? dim.width : this.opts.fontSizeLarge;\r\n r /= 1.5;\r\n\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, r, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n let cursorPos = -dim.width / 2.0;\r\n let cursorPosLeft = -dim.width / 2.0;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fillText(elementName, x + offsetX + cursorPos, y + this.opts.halfFontSizeLarge + offsetY);\r\n cursorPos += dim.width;\r\n\r\n if (charge) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(chargeText, x + offsetX + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += chargeWidth;\r\n }\r\n\r\n if (isotope > 0) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(isotopeText, x + offsetX + cursorPosLeft - isotopeWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPosLeft -= isotopeWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hydrogenWidth = 0;\r\n let hydrogenCountWidth = 0;\r\n\r\n if (hydrogens === 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n cursorPosLeft -= hydrogenWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.fillText('H', hx, hy);\r\n\r\n cursorPos += hydrogenWidth;\r\n } else if (hydrogens > 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n ctx.font = this.fontSmall;\r\n hydrogenCountWidth = ctx.measureText(hydrogens).width;\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillText('H', hx, hy);\r\n\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogens, hx + this.halfHydrogenWidth + hydrogenCountWidth, hy + this.opts.fifthFontSizeSmall);\r\n\r\n cursorPos += hydrogenWidth + this.halfHydrogenWidth + hydrogenCountWidth;\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let openParenthesisWidth = 0;\r\n let closeParenthesisWidth = 0;\r\n\r\n let element = attachedPseudoElement[key].element;\r\n let elementCount = attachedPseudoElement[key].count;\r\n let hydrogenCount = attachedPseudoElement[key].hydrogenCount;\r\n let elementCharge = attachedPseudoElement[key].charge;\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n openParenthesisWidth = ctx.measureText('(').width;\r\n closeParenthesisWidth = ctx.measureText(')').width;\r\n }\r\n\r\n let elementWidth = ctx.measureText(element).width;\r\n let elementCountWidth = 0;\r\n\r\n let elementChargeText = '';\r\n let elementChargeWidth = 0;\r\n\r\n hydrogenWidth = 0;\r\n\r\n if (hydrogenCount > 0) {\r\n hydrogenWidth = this.hydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n elementCountWidth = ctx.measureText(elementCount).width;\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n elementChargeText = getChargeText(elementCharge);\r\n elementChargeWidth = ctx.measureText(elementChargeText).width;\r\n }\r\n\r\n hydrogenCountWidth = 0;\r\n\r\n if (hydrogenCount > 1) {\r\n hydrogenCountWidth = ctx.measureText(hydrogenCount).width;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(element);\r\n\r\n if (elementCount > 0) {\r\n cursorPosLeft -= elementCountWidth;\r\n }\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= closeParenthesisWidth;\r\n ctx.fillText(')', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText('(', hx + cursorPos, hy);\r\n cursorPos += openParenthesisWidth;\r\n }\r\n }\r\n\r\n if (direction === 'left') {\r\n cursorPosLeft -= elementWidth;\r\n ctx.fillText(element, hx + cursorPosLeft, hy)\r\n } else {\r\n ctx.fillText(element, hx + cursorPos, hy);\r\n cursorPos += elementWidth;\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n ctx.fillText('H', hx + cursorPosLeft, hy);\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPosLeft + hydrogenWidth, hy + this.opts.fifthFontSizeSmall);\r\n }\r\n } else {\r\n ctx.fillText('H', hx + cursorPos, hy);\r\n cursorPos += hydrogenWidth;\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += hydrogenCountWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= openParenthesisWidth;\r\n ctx.fillText('(', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText(')', hx + cursorPos, hy);\r\n cursorPos += closeParenthesisWidth;\r\n }\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementCount, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, hy + this.opts.fifthFontSizeSmall);\r\n } else {\r\n ctx.fillText(elementCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += elementCountWidth;\r\n }\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementChargeText, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n } else {\r\n ctx.fillText(elementChargeText, hx + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += elementChargeWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\n getChargeText(charge) {\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Draws a dubug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n this.drawCircle(x, y, 2, color, true, true, debugText);\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Clear the canvas.\r\n *\r\n */\r\n clear() {\r\n this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = CanvasWrapper;","//@ts-check\r\n\r\nclass DecayPoint {\r\n\r\n /**\r\n * Enum values for Decay points\r\n * ALL use all variants of decay points\r\n * COO -CO-O- type of decay\r\n * CONH -CO-NH- type of decay\r\n * @return {{ALL: number, COO: number, CONH: number}}\r\n */\r\n static get VALUES() {\r\n return { ALL: 0, COO: 1, CONH: 2 };\r\n }\r\n}\r\n\r\nmodule.exports = DecayPoint;\r\n","//@ts-check\r\n\r\nclass DecayState {\r\n\r\n static get VALUES() {\r\n return { NO: 0, STANDARD: 1, SOURCE: 2, STANDARD_AND_SOURCE: 3};\r\n }\r\n}\r\n\r\nmodule.exports = DecayState;\r\n","\r\nclass Direction {\r\n\r\n static get VALUES() {\r\n return { N: 0, POLYKETIDE: 1, C: 2 };\r\n }\r\n\r\n static getProperValue(isPolyketide, vertexElement, vertexId, firstVertexId) {\r\n if (isPolyketide) {\r\n return this.VALUES.POLYKETIDE;\r\n }\r\n if (vertexElement === \"C\" && vertexId !== firstVertexId) {\r\n return this.VALUES.C;\r\n }\r\n return this.VALUES.N;\r\n }\r\n\r\n}\r\n\r\nmodule.exports= Direction;\r\n","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Atom = require('./Atom');\r\nconst Ring = require('./Ring');\r\nconst RingConnection = require('./RingConnection');\r\nconst CanvasWrapper = require('./CanvasWrapper');\r\nconst Graph = require('./Graph');\r\nconst SSSR = require('./SSSR');\r\nconst DecayState = require('./DecayState');\r\nconst ThemeManager = require('./ThemeManager');\r\n\r\n/**\r\n * The main class of the application representing the smiles drawer\r\n *\r\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\r\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\r\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} totalOverlapScore The current internal total overlap score.\r\n * @property {Object} defaultOptions The default options.\r\n * @property {Object} opts The merged options.\r\n * @property {Object} theme The current theme.\r\n */\r\nclass Drawer {\r\n /**\r\n * The constructor for the class SmilesDrawer.\r\n *\r\n * @param {Object} options An object containing custom values for different options. It is merged with the default options.\r\n */\r\n constructor(options) {\r\n this.graph = null;\r\n this.doubleBondConfigCount = 0;\r\n this.doubleBondConfig = null;\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n this.canvasWrapper = null;\r\n this.totalOverlapScore = 0;\r\n\r\n this.defaultOptions = {\r\n width: 500,\r\n height: 500,\r\n offsetX: 0, /* offsetX offset of canvas in page X. Typically canvas.offsetLeft */\r\n offsetY: 0, /* offsetY offset of canvas in page Y. Typically canvas.offsetTop */\r\n bondThickness: 0.6,\r\n bondLength: 15,\r\n shortBondLength: 0.85,\r\n bondSpacing: 0.18 * 15,\r\n atomVisualization: 'default',\r\n isomeric: true,\r\n debug: false,\r\n terminalCarbons: false,\r\n explicitHydrogens: false,\r\n overlapSensitivity: 0.42,\r\n overlapResolutionIterations: 1,\r\n compactDrawing: true,\r\n fontSizeLarge: 5,\r\n fontSizeSmall: 3,\r\n padding: 20.0,\r\n experimentalSSSR: false,\r\n kkThreshold: 0.1,\r\n kkInnerThreshold: 0.1,\r\n kkMaxIteration: 20000,\r\n kkMaxInnerIteration: 50,\r\n kkMaxEnergy: 1e9,\r\n drawDecayPoints: DecayState.VALUES.NO,\r\n decaySource: [],\r\n mouseTolerance: 3,\r\n themes: {\r\n dark: {\r\n C: '#fff',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#fff',\r\n BACKGROUND: '#141414',\r\n DECAY: '#027c21'\r\n },\r\n light: {\r\n C: '#222',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#222',\r\n BACKGROUND: '#fff',\r\n DECAY: '#027c21'\r\n }\r\n }\r\n };\r\n\r\n this.opts = this.extend(true, this.defaultOptions, options);\r\n this.opts.halfBondSpacing = this.opts.bondSpacing / 2.0;\r\n this.opts.bondLengthSq = this.opts.bondLength * this.opts.bondLength;\r\n this.opts.halfFontSizeLarge = this.opts.fontSizeLarge / 2.0;\r\n this.opts.quarterFontSizeLarge = this.opts.fontSizeLarge / 4.0;\r\n this.opts.fifthFontSizeSmall = this.opts.fontSizeSmall / 5.0;\r\n\r\n // Set the default theme.\r\n this.theme = this.opts.themes.dark;\r\n\r\n this.drawDecayPoints = this.opts.drawDecayPoints;\r\n }\r\n\r\n /**\r\n * A helper method to extend the default options with user supplied ones.\r\n */\r\n extend() {\r\n let that = this;\r\n let extended = {};\r\n let deep = false;\r\n let i = 0;\r\n let length = arguments.length;\r\n\r\n if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {\r\n deep = arguments[0];\r\n i++;\r\n }\r\n\r\n let merge = function (obj) {\r\n for (var prop in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, prop)) {\r\n if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\r\n extended[prop] = that.extend(true, extended[prop], obj[prop]);\r\n } else {\r\n extended[prop] = obj[prop];\r\n }\r\n }\r\n }\r\n };\r\n\r\n for (; i < length; i++) {\r\n let obj = arguments[i];\r\n merge(obj);\r\n }\r\n\r\n return extended;\r\n }\r\n\r\n /**\r\n * Is setup to draw decay points?\r\n * when boolean this.drawDecayPoint is true then return isDecay\r\n * @param isDecay bool - edge.isDecay\r\n * @returns {Boolean}\r\n */\r\n isDrawDecayPoint(isDecay) {\r\n return this.drawDecayPoints !== DecayState.VALUES.NO && isDecay;\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to a canvas element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n this.initDraw(data, themeName, infoOnly);\r\n\r\n if (!this.infoOnly) {\r\n this.themeManager = new ThemeManager(this.opts.themes, themeName);\r\n this.canvasWrapper = new CanvasWrapper(target, this.themeManager, this.opts);\r\n }\r\n\r\n if (!infoOnly) {\r\n this.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n\r\n if (this.opts.debug) {\r\n console.log(this.graph);\r\n console.log(this.rings);\r\n console.log(this.ringConnections);\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n if (this.canvasWrapper) {\r\n this.canvasWrapper.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of rings this edge is a part of.\r\n *\r\n * @param {Number} edgeId The id of an edge.\r\n * @returns {Number} The number of rings the provided edge is part of.\r\n */\r\n edgeRingCount(edgeId) {\r\n let edge = this.graph.edges[edgeId];\r\n let a = this.graph.vertices[edge.sourceId];\r\n let b = this.graph.vertices[edge.targetId];\r\n\r\n return Math.min(a.value.rings.length, b.value.rings.length);\r\n }\r\n\r\n /**\r\n * Returns an array containing the bridged rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all bridged rings associated with this molecule.\r\n */\r\n getBridgedRings() {\r\n let bridgedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n bridgedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return bridgedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all fused rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all fused rings associated with this molecule.\r\n */\r\n getFusedRings() {\r\n let fusedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isFused) {\r\n fusedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return fusedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all spiros associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all spiros associated with this molecule.\r\n */\r\n getSpiros() {\r\n let spiros = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isSpiro) {\r\n spiros.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return spiros;\r\n }\r\n\r\n /**\r\n * Returns a string containing a semicolon and new-line separated list of ring properties: Id; Members Count; Neighbours Count; IsSpiro; IsFused; IsBridged; Ring Count (subrings of bridged rings)\r\n *\r\n * @returns {String} A string as described in the method description.\r\n */\r\n printRingInfo() {\r\n let result = '';\r\n for (let i = 0; i < this.rings.length; i++) {\r\n const ring = this.rings[i];\r\n\r\n result += ring.id + ';';\r\n result += ring.members.length + ';';\r\n result += ring.neighbours.length + ';';\r\n result += ring.isSpiro ? 'true;' : 'false;';\r\n result += ring.isFused ? 'true;' : 'false;';\r\n result += ring.isBridged ? 'true;' : 'false;';\r\n result += ring.rings.length + ';';\r\n result += '\\n';\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Rotates the drawing to make the widest dimension horizontal.\r\n */\r\n rotateDrawing() {\r\n // Rotate the vertices to make the molecule align horizontally\r\n // Find the longest distance\r\n let a = 0;\r\n let b = 0;\r\n let maxDist = 0;\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertexA = this.graph.vertices[i];\r\n\r\n if (!vertexA.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n for (let j = i + 1; j < this.graph.vertices.length; j++) {\r\n let vertexB = this.graph.vertices[j];\r\n\r\n if (!vertexB.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = vertexA.position.distanceSq(vertexB.position);\r\n\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n a = i;\r\n b = j;\r\n }\r\n }\r\n }\r\n\r\n let angle = -Vector2.subtract(this.graph.vertices[a].position, this.graph.vertices[b].position).angle();\r\n\r\n if (!isNaN(angle)) {\r\n // Round to 30 degrees\r\n let remainder = angle % 0.523599;\r\n\r\n // Round either up or down in 30 degree steps\r\n if (remainder < 0.2617995) {\r\n angle = angle - remainder;\r\n } else {\r\n angle += 0.523599 - remainder;\r\n }\r\n\r\n // Finally, rotate everything\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (i === b) {\r\n continue;\r\n }\r\n\r\n this.graph.vertices[i].position.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.rings[i].center.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.totalOverlapScore;\r\n }\r\n\r\n /**\r\n * Returns the ring count of the current molecule.\r\n *\r\n * @returns {Number} The ring count.\r\n */\r\n getRingCount() {\r\n return this.rings.length;\r\n }\r\n\r\n /**\r\n * Checks whether or not the current molecule a bridged ring.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not the current molecule a bridged ring.\r\n */\r\n hasBridgedRing() {\r\n return this.bridgedRing;\r\n }\r\n\r\n /**\r\n * Returns the number of heavy atoms (non-hydrogen) in the current molecule.\r\n *\r\n * @returns {Number} The heavy atom count.\r\n */\r\n getHeavyAtomCount() {\r\n let hac = 0;\r\n\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.element !== 'H') {\r\n hac++;\r\n }\r\n }\r\n\r\n return hac;\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n let molecularFormula = '';\r\n let counts = new Map();\r\n\r\n // Initialize element count\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n let atom = this.graph.vertices[i].value;\r\n\r\n if (counts.has(atom.element)) {\r\n counts.set(atom.element, counts.get(atom.element) + 1);\r\n } else {\r\n counts.set(atom.element, 1);\r\n }\r\n\r\n // Hydrogens attached to a chiral center were added as vertices,\r\n // those in non chiral brackets are added here\r\n if (atom.bracket && !atom.bracket.chirality) {\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + atom.bracket.hcount);\r\n } else {\r\n counts.set('H', atom.bracket.hcount);\r\n }\r\n }\r\n\r\n // Add the implicit hydrogens according to valency, exclude\r\n // bracket atoms as they were handled and always have the number\r\n // of hydrogens specified explicitly\r\n if (!atom.bracket) {\r\n let nHydrogens = Atom.maxBonds[atom.element] - atom.bondCount;\r\n\r\n if (atom.isPartOfAromaticRing) {\r\n nHydrogens--;\r\n }\r\n\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + nHydrogens);\r\n } else {\r\n counts.set('H', nHydrogens);\r\n }\r\n }\r\n }\r\n\r\n if (counts.has('C')) {\r\n let count = counts.get('C');\r\n molecularFormula += 'C' + (count > 1 ? count : '');\r\n counts.delete('C');\r\n }\r\n\r\n if (counts.has('H')) {\r\n let count = counts.get('H');\r\n molecularFormula += 'H' + (count > 1 ? count : '');\r\n counts.delete('H');\r\n }\r\n\r\n let elements = Object.keys(Atom.atomicNumbers).sort();\r\n\r\n elements.map(e => {\r\n if (counts.has(e)) {\r\n let count = counts.get(e);\r\n molecularFormula += e + (count > 1 ? count : '');\r\n }\r\n });\r\n\r\n return molecularFormula;\r\n }\r\n\r\n /**\r\n * Returns the type of the ringbond (e.g. '=' for a double bond). The ringbond represents the break in a ring introduced when creating the MST. If the two vertices supplied as arguments are not part of a common ringbond, the method returns null.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(String|null)} Returns the ringbond type or null, if the two supplied vertices are not connected by a ringbond.\r\n */\r\n getRingbondType(vertexA, vertexB) {\r\n // Checks whether the two vertices are the ones connecting the ring\r\n // and what the bond type should be.\r\n if (vertexA.value.getRingbondCount() < 1 || vertexB.value.getRingbondCount() < 1) {\r\n return null;\r\n }\r\n\r\n for (var i = 0; i < vertexA.value.ringbonds.length; i++) {\r\n for (var j = 0; j < vertexB.value.ringbonds.length; j++) {\r\n // if(i != j) continue;\r\n if (vertexA.value.ringbonds[i].id === vertexB.value.ringbonds[j].id) {\r\n // If the bonds are equal, it doesn't matter which bond is returned.\r\n // if they are not equal, return the one that is not the default (\"-\")\r\n if (vertexA.value.ringbonds[i].bondType === '-') {\r\n return vertexB.value.ringbonds[j].bond;\r\n } else {\r\n return vertexA.value.ringbonds[i].bond;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n initDraw(data, themeName, infoOnly) {\r\n this.data = data;\r\n this.infoOnly = infoOnly;\r\n\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n\r\n this.graph = new Graph(data, this.opts.isomeric, this.opts);\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n this.bridgedRing = false;\r\n\r\n // Reset those, in case the previous drawn SMILES had a dangling \\ or /\r\n this.doubleBondConfigCount = null;\r\n this.doubleBondConfig = null;\r\n\r\n this.initRings();\r\n this.initHydrogens();\r\n this.graph.findDecayPoints();\r\n }\r\n\r\n processGraph() {\r\n this.position();\r\n\r\n // Restore the ring information (removes bridged rings and replaces them with the original, multiple, rings)\r\n this.restoreRingInformation();\r\n\r\n // Atoms bonded to the same ring atom\r\n this.resolvePrimaryOverlaps();\r\n\r\n let overlapScore = this.getOverlapScore();\r\n\r\n this.totalOverlapScore = this.getOverlapScore().total;\r\n\r\n for (var o = 0; o < this.opts.overlapResolutionIterations; o++) {\r\n for (var i = 0; i < this.graph.edges.length; i++) {\r\n let edge = this.graph.edges[i];\r\n if (this.isEdgeRotatable(edge)) {\r\n let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\r\n let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\r\n\r\n // Only rotate the shorter subtree\r\n let a = edge.targetId;\r\n let b = edge.sourceId;\r\n\r\n if (subTreeDepthA > subTreeDepthB) {\r\n a = edge.sourceId;\r\n b = edge.targetId;\r\n }\r\n\r\n let subTreeOverlap = this.getSubtreeOverlapScore(b, a, overlapScore.vertexScores);\r\n if (subTreeOverlap.value > this.opts.overlapSensitivity) {\r\n let vertexA = this.graph.vertices[a];\r\n let vertexB = this.graph.vertices[b];\r\n let neighboursB = vertexB.getNeighbours(a);\r\n\r\n if (neighboursB.length === 1) {\r\n let neighbour = this.graph.vertices[neighboursB[0]];\r\n let angle = neighbour.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbour.id, vertexB.id, angle, vertexB.position);\r\n // If the new overlap is bigger, undo change\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbour.id, vertexB.id, -angle, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n } else if (neighboursB.length === 2) {\r\n // Switch places / sides\r\n // If vertex a is in a ring, do nothing\r\n if (vertexB.value.rings.length !== 0 && vertexA.value.rings.length !== 0) {\r\n continue;\r\n }\r\n\r\n let neighbourA = this.graph.vertices[neighboursB[0]];\r\n let neighbourB = this.graph.vertices[neighboursB[1]];\r\n\r\n if (neighbourA.value.rings.length === 1 && neighbourB.value.rings.length === 1) {\r\n // Both neighbours in same ring. TODO: does this create problems with wedges? (up = down and vice versa?)\r\n if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\r\n continue;\r\n }\r\n // TODO: Rotate circle\r\n } else if (neighbourA.value.rings.length !== 0 || neighbourB.value.rings.length !== 0) {\r\n continue;\r\n } else {\r\n let angleA = neighbourA.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n let angleB = neighbourB.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbourA.id, vertexB.id, angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, angleB, vertexB.position);\r\n\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbourA.id, vertexB.id, -angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, -angleB, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n }\r\n }\r\n\r\n overlapScore = this.getOverlapScore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.resolveSecondaryOverlaps(overlapScore.scores);\r\n\r\n if (this.opts.isomeric) {\r\n this.annotateStereochemistry();\r\n }\r\n\r\n // Initialize pseudo elements or shortcuts\r\n if (this.opts.compactDrawing && this.opts.atomVisualization === 'default') {\r\n this.initPseudoElements();\r\n }\r\n\r\n this.rotateDrawing();\r\n }\r\n\r\n /**\r\n * Initializes rings and ringbonds for the current molecule.\r\n */\r\n initRings() {\r\n let openBonds = new Map();\r\n\r\n // Close the open ring bonds (spanning tree -> graph)\r\n for (let i = this.graph.vertices.length - 1; i >= 0; i--) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.ringbonds.length === 0) {\r\n continue;\r\n }\r\n\r\n for (let j = 0; j < vertex.value.ringbonds.length; j++) {\r\n let ringbondId = vertex.value.ringbonds[j].id;\r\n let ringbondBond = vertex.value.ringbonds[j].bond;\r\n\r\n // If the other ringbond id has not been discovered,\r\n // add it to the open bonds map and continue.\r\n // if the other ringbond id has already been discovered,\r\n // create a bond between the two atoms.\r\n if (!openBonds.has(ringbondId)) {\r\n openBonds.set(ringbondId, [vertex.id, ringbondBond]);\r\n } else {\r\n let sourceVertexId = vertex.id;\r\n let targetVertexId = openBonds.get(ringbondId)[0];\r\n let targetRingbondBond = openBonds.get(ringbondId)[1];\r\n let edge = new Edge(sourceVertexId, targetVertexId, 1);\r\n edge.setBondType(targetRingbondBond || ringbondBond || '-');\r\n let edgeId = this.graph.addEdge(edge);\r\n let targetVertex = this.graph.vertices[targetVertexId];\r\n\r\n vertex.addRingbondChild(targetVertexId, j);\r\n vertex.value.addNeighbouringElement(targetVertex.value.element);\r\n targetVertex.addRingbondChild(sourceVertexId, j);\r\n targetVertex.value.addNeighbouringElement(vertex.value.element);\r\n vertex.edges.push(edgeId);\r\n targetVertex.edges.push(edgeId);\r\n\r\n openBonds.delete(ringbondId);\r\n }\r\n }\r\n }\r\n\r\n // Get the rings in the graph (the SSSR)\r\n let rings = SSSR.getRings(this.graph, this.opts.experimentalSSSR);\r\n\r\n if (rings === null) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < rings.length; i++) {\r\n let ringVertices = [...rings[i]];\r\n let ringId = this.addRing(new Ring(ringVertices));\r\n\r\n // Add the ring to the atoms\r\n for (let j = 0; j < ringVertices.length; j++) {\r\n this.graph.vertices[ringVertices[j]].value.rings.push(ringId);\r\n }\r\n }\r\n\r\n // Find connection between rings\r\n // Check for common vertices and create ring connections. This is a bit\r\n // ugly, but the ringcount is always fairly low (< 100)\r\n for (let i = 0; i < this.rings.length - 1; i++) {\r\n for (let j = i + 1; j < this.rings.length; j++) {\r\n let a = this.rings[i];\r\n let b = this.rings[j];\r\n let ringConnection = new RingConnection(a, b);\r\n\r\n // If there are no vertices in the ring connection, then there\r\n // is no ring connection\r\n if (ringConnection.vertices.size > 0) {\r\n this.addRingConnection(ringConnection);\r\n }\r\n }\r\n }\r\n\r\n // Add neighbours to the rings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n ring.neighbours = RingConnection.getNeighbours(this.ringConnections, ring.id);\r\n }\r\n\r\n // Anchor the ring to one of it's members, so that the ring center will always\r\n // be tied to a single vertex when doing repositionings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n this.graph.vertices[ring.members[0]].value.addAnchoredRing(ring.id);\r\n }\r\n\r\n // Backup the ring information to restore after placing the bridged ring.\r\n // This is needed in order to identify aromatic rings and stuff like this in\r\n // rings that are member of the superring.\r\n this.backupRingInformation();\r\n\r\n\r\n // Replace rings contained by a larger bridged ring with a bridged ring\r\n while (this.rings.length > 0) {\r\n let id = -1;\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isPartOfBridgedRing(ring.id) && !ring.isBridged) {\r\n id = ring.id;\r\n }\r\n }\r\n\r\n if (id === -1) {\r\n break;\r\n }\r\n\r\n let ring = this.getRing(id);\r\n\r\n let involvedRings = this.getBridgedRingRings(ring.id);\r\n\r\n this.bridgedRing = true;\r\n this.createBridgedRing(involvedRings, ring.members[0]);\r\n\r\n // Remove the rings\r\n for (let i = 0; i < involvedRings.length; i++) {\r\n this.removeRing(involvedRings[i]);\r\n }\r\n }\r\n }\r\n\r\n initHydrogens() {\r\n // Do not draw hydrogens except when they are connected to a stereocenter connected to two or more rings.\r\n if (!this.opts.explicitHydrogens) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.element !== 'H') {\r\n continue;\r\n }\r\n\r\n // Hydrogens should have only one neighbour, so just take the first\r\n // Also set hasHydrogen true on connected atom\r\n let neighbour = this.graph.vertices[vertex.neighbours[0]];\r\n neighbour.value.hasHydrogen = true;\r\n\r\n if (!neighbour.value.isStereoCenter || neighbour.value.rings.length < 2 && !neighbour.value.bridgedRing ||\r\n neighbour.value.bridgedRing && neighbour.value.originalRings.length < 2) {\r\n vertex.value.isDrawn = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns all rings connected by bridged bonds starting from the ring with the supplied ring id.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array containing all ring ids of rings part of a bridged ring system.\r\n */\r\n getBridgedRingRings(ringId) {\r\n let involvedRings = Array();\r\n let that = this;\r\n\r\n let recurse = function (r) {\r\n let ring = that.getRing(r);\r\n\r\n involvedRings.push(r);\r\n\r\n for (let i = 0; i < ring.neighbours.length; i++) {\r\n let n = ring.neighbours[i];\r\n\r\n if (involvedRings.indexOf(n) === -1 &&\r\n n !== r &&\r\n RingConnection.isBridge(that.ringConnections, that.graph.vertices, r, n)) {\r\n recurse(n);\r\n }\r\n }\r\n };\r\n\r\n recurse(ringId);\r\n\r\n return ArrayHelper.unique(involvedRings);\r\n }\r\n\r\n /**\r\n * Checks whether or not a ring is part of a bridged ring.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not the supplied ring (by id) is part of a bridged ring system.\r\n */\r\n isPartOfBridgedRing(ringId) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].containsRing(ringId) &&\r\n this.ringConnections[i].isBridge(this.graph.vertices)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Creates a bridged ring.\r\n *\r\n * @param {Number[]} ringIds An array of ids of rings involved in the bridged ring.\r\n * @param {Number} sourceVertexId The vertex id to start the bridged ring discovery from.\r\n * @returns {Ring} The bridged ring.\r\n */\r\n createBridgedRing(ringIds, sourceVertexId) {\r\n let ringMembers = new Set();\r\n let vertices = new Set();\r\n let neighbours = new Set();\r\n\r\n for (let i = 0; i < ringIds.length; i++) {\r\n let ring = this.getRing(ringIds[i]);\r\n ring.isPartOfBridged = true;\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n vertices.add(ring.members[j]);\r\n }\r\n\r\n for (let j = 0; j < ring.neighbours.length; j++) {\r\n let id = ring.neighbours[j];\r\n\r\n if (ringIds.indexOf(id) === -1) {\r\n neighbours.add(ring.neighbours[j]);\r\n }\r\n }\r\n }\r\n\r\n // A vertex is part of the bridged ring if it only belongs to\r\n // one of the rings (or to another ring\r\n // which is not part of the bridged ring).\r\n let leftovers = new Set();\r\n\r\n for (let id of vertices) {\r\n let vertex = this.graph.vertices[id];\r\n let intersection = ArrayHelper.intersection(ringIds, vertex.value.rings);\r\n\r\n if (vertex.value.rings.length === 1 || intersection.length === 1) {\r\n ringMembers.add(vertex.id);\r\n } else {\r\n leftovers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Vertices can also be part of multiple rings and lay on the bridged ring,\r\n // however, they have to have at least two neighbours that are not part of\r\n // two rings\r\n let insideRing = Array();\r\n for (let id of leftovers) {\r\n let vertex = this.graph.vertices[id];\r\n let onRing = false;\r\n\r\n for (let j = 0; j < vertex.edges.length; j++) {\r\n if (this.edgeRingCount(vertex.edges[j]) === 1) {\r\n onRing = true;\r\n }\r\n }\r\n\r\n if (onRing) {\r\n vertex.value.isBridgeNode = true;\r\n ringMembers.add(vertex.id);\r\n } else {\r\n vertex.value.isBridge = true;\r\n ringMembers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Create the ring\r\n let ring = new Ring([...ringMembers]);\r\n this.addRing(ring);\r\n\r\n ring.isBridged = true;\r\n ring.neighbours = [...neighbours];\r\n for (let i = 0; i < ringIds.length; i++) {\r\n ring.rings.push(this.getRing(ringIds[i]).clone());\r\n }\r\n\r\n for (let i = 0; i < ring.members.length; i++) {\r\n this.graph.vertices[ring.members[i]].value.bridgedRing = ring.id;\r\n }\r\n\r\n // Atoms inside the ring are no longer part of a ring but are now\r\n // associated with the bridged ring\r\n for (let i = 0; i < insideRing.length; i++) {\r\n let vertex = this.graph.vertices[insideRing[i]];\r\n vertex.value.rings = Array();\r\n }\r\n\r\n // Remove former rings from members of the bridged ring and add the bridged ring\r\n for (let id of ringMembers) {\r\n let vertex = this.graph.vertices[id];\r\n vertex.value.rings = ArrayHelper.removeAll(vertex.value.rings, ringIds);\r\n vertex.value.rings.push(ring.id);\r\n }\r\n\r\n // Remove all the ring connections no longer used\r\n for (let i = 0; i < ringIds.length; i++) {\r\n for (let j = i + 1; j < ringIds.length; j++) {\r\n this.removeRingConnectionsBetween(ringIds[i], ringIds[j]);\r\n }\r\n }\r\n\r\n // Update the ring connections and add this ring to the neighbours neighbours\r\n for (let id of neighbours) {\r\n let connections = this.getRingConnections(id, ringIds);\r\n\r\n for (let j = 0; j < connections.length; j++) {\r\n this.getRingConnection(connections[j]).updateOther(ring.id, id);\r\n }\r\n\r\n this.getRing(id).neighbours.push(ring.id);\r\n }\r\n\r\n return ring;\r\n }\r\n\r\n /**\r\n * Checks whether or not two vertices are in the same ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices are in the same ring.\r\n */\r\n areVerticesInSameRing(vertexA, vertexB) {\r\n // This is a little bit lighter (without the array and push) than\r\n // getCommonRings().length > 0\r\n for (let i = 0; i < vertexA.value.rings.length; i++) {\r\n for (let j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] === vertexB.value.rings[j]) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array of ring ids shared by both vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Number[]} An array of ids of rings shared by the two vertices.\r\n */\r\n getCommonRings(vertexA, vertexB) {\r\n let commonRings = Array();\r\n\r\n for (var i = 0; i < vertexA.value.rings.length; i++) {\r\n for (var j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] == vertexB.value.rings[j]) {\r\n commonRings.push(vertexA.value.rings[i]);\r\n }\r\n }\r\n }\r\n\r\n return commonRings;\r\n }\r\n\r\n /**\r\n * Returns the aromatic or largest ring shared by the two vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(Ring|null)} If an aromatic common ring exists, that ring, else the largest (non-aromatic) ring, else null.\r\n */\r\n getLargestOrAromaticCommonRing(vertexA, vertexB) {\r\n let commonRings = this.getCommonRings(vertexA, vertexB);\r\n let maxSize = 0;\r\n let largestCommonRing = null;\r\n\r\n for (let i = 0; i < commonRings.length; i++) {\r\n let ring = this.getRing(commonRings[i]);\r\n let size = ring.getSize();\r\n\r\n if (ring.isBenzeneLike(this.graph.vertices)) {\r\n return ring;\r\n } else if (size > maxSize) {\r\n maxSize = size;\r\n largestCommonRing = ring;\r\n }\r\n }\r\n\r\n return largestCommonRing;\r\n }\r\n\r\n /**\r\n * Returns an array of vertices positioned at a specified location.\r\n *\r\n * @param {Vector2} position The position to search for vertices.\r\n * @param {Number} radius The radius within to search.\r\n * @param {Number} excludeVertexId A vertex id to be excluded from the search results.\r\n * @returns {Number[]} An array containing vertex ids in a given location.\r\n */\r\n getVerticesAt(position, radius, excludeVertexId) {\r\n let locals = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.id === excludeVertexId || !vertex.positioned) {\r\n continue;\r\n }\r\n\r\n let distance = position.distanceSq(vertex.position);\r\n\r\n if (distance <= radius * radius) {\r\n locals.push(vertex.id);\r\n }\r\n }\r\n\r\n return locals;\r\n }\r\n\r\n /**\r\n * Returns the closest vertex (connected as well as unconnected).\r\n *\r\n * @param {Vertex} vertex The vertex of which to find the closest other vertex.\r\n * @returns {Vertex} The closest vertex.\r\n */\r\n getClosestVertex(vertex) {\r\n let minDist = 99999;\r\n let minVertex = null;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i];\r\n\r\n if (v.id === vertex.id) {\r\n continue;\r\n }\r\n\r\n let distSq = vertex.position.distanceSq(v.position);\r\n\r\n if (distSq < minDist) {\r\n minDist = distSq;\r\n minVertex = v;\r\n }\r\n }\r\n\r\n return minVertex;\r\n }\r\n\r\n /**\r\n * Add a ring to this representation of a molecule.\r\n *\r\n * @param {Ring} ring A new ring.\r\n * @returns {Number} The ring id of the new ring.\r\n */\r\n addRing(ring) {\r\n ring.id = this.ringIdCounter++;\r\n this.rings.push(ring);\r\n\r\n return ring.id;\r\n }\r\n\r\n /**\r\n * Removes a ring from the array of rings associated with the current molecule.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n removeRing(ringId) {\r\n this.rings = this.rings.filter(function (item) {\r\n return item.id !== ringId;\r\n });\r\n\r\n // Also remove ring connections involving this ring\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.firstRingId !== ringId && item.secondRingId !== ringId;\r\n });\r\n\r\n // Remove the ring as neighbour of other rings\r\n for (var i = 0; i < this.rings.length; i++) {\r\n let r = this.rings[i];\r\n r.neighbours = r.neighbours.filter(function (item) {\r\n return item !== ringId;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets a ring object from the array of rings associated with the current molecule by its id. The ring id is not equal to the index, since rings can be added and removed when processing bridged rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Ring} A ring associated with the current molecule.\r\n */\r\n getRing(ringId) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].id == ringId) {\r\n return this.rings[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Add a ring connection to this representation of a molecule.\r\n *\r\n * @param {RingConnection} ringConnection A new ringConnection.\r\n * @returns {Number} The ring connection id of the new ring connection.\r\n */\r\n addRingConnection(ringConnection) {\r\n ringConnection.id = this.ringConnectionIdCounter++;\r\n this.ringConnections.push(ringConnection);\r\n\r\n return ringConnection.id;\r\n }\r\n\r\n /**\r\n * Removes a ring connection from the array of rings connections associated with the current molecule.\r\n *\r\n * @param {Number} ringConnectionId A ring connection id.\r\n */\r\n removeRingConnection(ringConnectionId) {\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.id !== ringConnectionId;\r\n });\r\n }\r\n\r\n /**\r\n * Removes all ring connections between two vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n */\r\n removeRingConnectionsBetween(vertexIdA, vertexIdB) {\r\n let toRemove = Array();\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let ringConnection = this.ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === vertexIdA && ringConnection.secondRingId === vertexIdB ||\r\n ringConnection.firstRingId === vertexIdB && ringConnection.secondRingId === vertexIdA) {\r\n toRemove.push(ringConnection.id);\r\n }\r\n }\r\n\r\n for (let i = 0; i < toRemove.length; i++) {\r\n this.removeRingConnection(toRemove[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Get a ring connection with a given id.\r\n *\r\n * @param {Number} id\r\n * @returns {RingConnection} The ring connection with the specified id.\r\n */\r\n getRingConnection(id) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].id == id) {\r\n return this.ringConnections[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the ring connections between a ring and a set of rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @param {Number[]} ringIds An array of ring ids.\r\n * @returns {Number[]} An array of ring connection ids.\r\n */\r\n getRingConnections(ringId, ringIds) {\r\n let ringConnections = Array();\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let rc = this.ringConnections[i];\r\n\r\n for (let j = 0; j < ringIds.length; j++) {\r\n let id = ringIds[j];\r\n\r\n if (rc.firstRingId === ringId && rc.secondRingId === id ||\r\n rc.firstRingId === id && rc.secondRingId === ringId) {\r\n ringConnections.push(rc.id);\r\n }\r\n }\r\n }\r\n\r\n return ringConnections;\r\n }\r\n\r\n /**\r\n * Returns the overlap score of the current molecule based on its positioned vertices. The higher the score, the more overlaps occur in the structure drawing.\r\n *\r\n * @returns {Object} Returns the total overlap score and the overlap score of each vertex sorted by score (higher to lower). Example: { total: 99, scores: [ { id: 0, score: 22 }, ... ] }\r\n */\r\n getOverlapScore() {\r\n let total = 0.0;\r\n let overlapScores = new Float32Array(this.graph.vertices.length);\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n overlapScores[i] = 0;\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let j = this.graph.vertices.length;\r\n while (--j > i) {\r\n let a = this.graph.vertices[i];\r\n let b = this.graph.vertices[j];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = Vector2.subtract(a.position, b.position).lengthSq();\r\n\r\n if (dist < this.opts.bondLengthSq) {\r\n let weighted = (this.opts.bondLength - Math.sqrt(dist)) / this.opts.bondLength;\r\n total += weighted;\r\n overlapScores[i] += weighted;\r\n overlapScores[j] += weighted;\r\n }\r\n }\r\n }\r\n\r\n let sortable = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n sortable.push({\r\n id: i,\r\n score: overlapScores[i]\r\n });\r\n }\r\n\r\n sortable.sort(function (a, b) {\r\n return b.score - a.score;\r\n });\r\n\r\n return {\r\n total: total,\r\n scores: sortable,\r\n vertexScores: overlapScores\r\n };\r\n }\r\n\r\n /**\r\n * When drawing a double bond, choose the side to place the double bond. E.g. a double bond should always been drawn inside a ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @param {Vector2[]} sides An array containing the two normals of the line spanned by the two provided vertices.\r\n * @returns {Object} Returns an object containing the following information: {\r\n totalSideCount: Counts the sides of each vertex in the molecule, is an array [ a, b ],\r\n totalPosition: Same as position, but based on entire molecule,\r\n sideCount: Counts the sides of each neighbour, is an array [ a, b ],\r\n position: which side to position the second bond, is 0 or 1, represents the index in the normal array. This is based on only the neighbours\r\n anCount: the number of neighbours of vertexA,\r\n bnCount: the number of neighbours of vertexB\r\n }\r\n */\r\n chooseSide(vertexA, vertexB, sides) {\r\n // Check which side has more vertices\r\n // Get all the vertices connected to the both ends\r\n let an = vertexA.getNeighbours(vertexB.id);\r\n let bn = vertexB.getNeighbours(vertexA.id);\r\n let anCount = an.length;\r\n let bnCount = bn.length;\r\n\r\n // All vertices connected to the edge vertexA to vertexB\r\n let tn = ArrayHelper.merge(an, bn);\r\n\r\n // Only considering the connected vertices\r\n let sideCount = [0, 0];\r\n\r\n for (let i = 0; i < tn.length; i++) {\r\n let v = this.graph.vertices[tn[i]].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n sideCount[0]++;\r\n } else {\r\n sideCount[1]++;\r\n }\r\n }\r\n\r\n // Considering all vertices in the graph, this is to resolve ties\r\n // from the above side counts\r\n let totalSideCount = [0, 0];\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n totalSideCount[0]++;\r\n } else {\r\n totalSideCount[1]++;\r\n }\r\n }\r\n\r\n return {\r\n totalSideCount: totalSideCount,\r\n totalPosition: totalSideCount[0] > totalSideCount[1] ? 0 : 1,\r\n sideCount: sideCount,\r\n position: sideCount[0] > sideCount[1] ? 0 : 1,\r\n anCount: anCount,\r\n bnCount: bnCount\r\n };\r\n }\r\n\r\n /**\r\n * Sets the center for a ring.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n setRingCenter(ring) {\r\n let ringSize = ring.getSize();\r\n let total = new Vector2(0, 0);\r\n\r\n for (let i = 0; i < ringSize; i++) {\r\n total.add(this.graph.vertices[ring.members[i]].position);\r\n }\r\n\r\n ring.center = total.divide(ringSize);\r\n }\r\n\r\n /**\r\n * Gets the center of a ring contained within a bridged ring and containing a given vertex.\r\n *\r\n * @param {Ring} ring A bridged ring.\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {Vector2} The center of the subring that containing the vertex.\r\n */\r\n getSubringCenter(ring, vertex) {\r\n let rings = vertex.value.originalRings;\r\n let center = ring.center;\r\n let smallest = Number.MAX_VALUE;\r\n\r\n // Always get the smallest ring.\r\n for (let i = 0; i < rings.length; i++) {\r\n for (let j = 0; j < ring.rings.length; j++) {\r\n if (rings[i] === ring.rings[j].id) {\r\n if (ring.rings[j].getSize() < smallest) {\r\n center = ring.rings[j].center;\r\n smallest = ring.rings[j].getSize();\r\n }\r\n }\r\n }\r\n }\r\n\r\n return center;\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let that = this;\r\n let drawn = Array(this.graph.edges.length);\r\n drawn.fill(false);\r\n\r\n this.graph.traverseBF(0, function (vertex) {\r\n let edges = that.graph.getEdges(vertex.id);\r\n for (let i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n that.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isRingAromatic(ring)) {\r\n this.canvasWrapper.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bonds to the canvas.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let that = this;\r\n let edge = this.graph.edges[edgeId];\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n let elementA = vertexA.value.element;\r\n let elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && this.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position;\r\n let b = vertexB.position;\r\n let normals = this.getEdgeNormals(edge);\r\n\r\n // Create a point on each side of the line\r\n let sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || this.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && this.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = this.areVerticesInSameRing(vertexA, vertexB);\r\n let s = this.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = this.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n }\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n this.canvasWrapper.drawLine(line, true);\r\n } else {\r\n this.canvasWrapper.drawLine(line);\r\n }\r\n\r\n // The normal edge\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.center || vertexA.isTerminal() && vertexB.isTerminal()) {\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1) {\r\n // Both lines are the same length here\r\n // Add the spacing to the edges (which are of unit length)\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.sideCount[0] > s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.sideCount[0] < s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] > s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] <= s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n this.canvasWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.wedge === 'down') {\r\n this.canvasWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else {\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n this.canvasWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(this.graph.vertices);\r\n let isTerminal = this.opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (this.opts.atomVisualization === 'allballs') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || this.graph.vertices.length === 1) {\r\n if (this.opts.atomVisualization === 'default') {\r\n this.canvasWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (this.opts.atomVisualization === 'balls') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = this.graph.vertices[vertex.neighbours[0]].position;\r\n let b = this.graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n this.canvasWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n // this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (this.opts.debug) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let center = this.rings[i].center;\r\n this.canvasWrapper.drawDebugPoint(center.x, center.y, 'r: ' + this.rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Position the vertices according to their bonds and properties.\r\n */\r\n position() {\r\n let startVertex = null;\r\n\r\n // Always start drawing at a bridged ring if there is one\r\n // If not, start with a ring\r\n // else, start with 0\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.bridgedRing !== null) {\r\n startVertex = this.graph.vertices[i];\r\n break;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n startVertex = this.graph.vertices[this.rings[i].members[0]];\r\n }\r\n }\r\n\r\n if (this.rings.length > 0 && startVertex === null) {\r\n startVertex = this.graph.vertices[this.rings[0].members[0]];\r\n }\r\n\r\n if (startVertex === null) {\r\n startVertex = this.graph.vertices[0];\r\n }\r\n\r\n this.createNextBond(startVertex, null, 0.0);\r\n }\r\n\r\n /**\r\n * Stores the current information associated with rings.\r\n */\r\n backupRingInformation() {\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings.push(this.rings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n this.originalRingConnections.push(this.ringConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.backupRings();\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recently backed up information associated with rings.\r\n */\r\n restoreRingInformation() {\r\n // Get the subring centers from the bridged rings\r\n let bridgedRings = this.getBridgedRings();\r\n\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n for (let i = 0; i < bridgedRings.length; i++) {\r\n let bridgedRing = bridgedRings[i];\r\n\r\n for (var j = 0; j < bridgedRing.rings.length; j++) {\r\n let ring = bridgedRing.rings[j];\r\n this.originalRings[ring.id].center = ring.center;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings.push(this.originalRings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.originalRingConnections.length; i++) {\r\n this.ringConnections.push(this.originalRingConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.restoreRings();\r\n }\r\n }\r\n\r\n // TODO: This needs some cleaning up\r\n\r\n /**\r\n * Creates a new ring, that is, positiones all the vertices inside a ring.\r\n *\r\n * @param {Ring} ring The ring to position.\r\n * @param {(Vector2|null)} [center=null] The center of the ring to be created.\r\n * @param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.\r\n * @param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.\r\n * @param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.\r\n */\r\n createRing(ring, center = null, startVertex = null, previousVertex = null) {\r\n if (ring.positioned) {\r\n return;\r\n }\r\n\r\n center = center ? center : new Vector2(0, 0);\r\n\r\n let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);\r\n let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let angle = MathHelper.centralAngle(ring.getSize());\r\n\r\n ring.centralAngle = angle;\r\n\r\n let a = startingAngle;\r\n let that = this;\r\n let startVertexId = (startVertex) ? startVertex.id : null;\r\n\r\n if (ring.members.indexOf(startVertexId) === -1) {\r\n if (startVertex) {\r\n startVertex.positioned = false;\r\n }\r\n\r\n startVertexId = ring.members[0];\r\n }\r\n\r\n // If the ring is bridged, then draw the vertices inside the ring\r\n // using a force based approach\r\n if (ring.isBridged) {\r\n this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength,\r\n this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration,\r\n this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);\r\n ring.positioned = true;\r\n\r\n // Update the center of the bridged ring\r\n this.setRingCenter(ring);\r\n center = ring.center;\r\n\r\n // Setting the centers for the subrings\r\n for (let i = 0; i < ring.rings.length; i++) {\r\n this.setRingCenter(ring.rings[i]);\r\n }\r\n } else {\r\n ring.eachMember(this.graph.vertices, function (v) {\r\n let vertex = that.graph.vertices[v];\r\n\r\n if (!vertex.positioned) {\r\n vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);\r\n }\r\n\r\n a += angle;\r\n\r\n if (!ring.isBridged || ring.rings.length < 3) {\r\n vertex.angle = a;\r\n vertex.positioned = true;\r\n }\r\n }, startVertexId, (previousVertex) ? previousVertex.id : null);\r\n }\r\n\r\n ring.positioned = true;\r\n ring.center = center;\r\n\r\n // Draw neighbours in decreasing order of connectivity\r\n for (let i = 0; i < orderedNeighbours.length; i++) {\r\n let neighbour = this.getRing(orderedNeighbours[i].neighbour);\r\n\r\n if (neighbour.positioned) {\r\n continue;\r\n }\r\n\r\n let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);\r\n\r\n if (vertices.length === 2) {\r\n // This ring is a fused ring\r\n ring.isFused = true;\r\n neighbour.isFused = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n let vertexB = this.graph.vertices[vertices[1]];\r\n\r\n // Get middle between vertex A and B\r\n let midpoint = Vector2.midpoint(vertexA.position, vertexB.position);\r\n\r\n // Get the normals to the line between A and B\r\n let normals = Vector2.normals(vertexA.position, vertexB.position);\r\n\r\n // Normalize the normals\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n // Set length from middle of side to center (the apothem)\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n let apothem = MathHelper.apothem(r, neighbour.getSize());\r\n\r\n normals[0].multiplyScalar(apothem).add(midpoint);\r\n normals[1].multiplyScalar(apothem).add(midpoint);\r\n\r\n // Pick the normal which results in a larger distance to the previous center\r\n // Also check whether it's inside another ring\r\n let nextCenter = normals[0];\r\n if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {\r\n nextCenter = normals[1];\r\n }\r\n\r\n // Get the vertex (A or B) which is in clock-wise direction of the other\r\n let posA = Vector2.subtract(vertexA.position, nextCenter);\r\n let posB = Vector2.subtract(vertexB.position, nextCenter);\r\n\r\n if (posA.clockwise(posB) === -1) {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA, vertexB);\r\n }\r\n } else {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexB, vertexA);\r\n }\r\n }\r\n } else if (vertices.length === 1) {\r\n // This ring is a spiro\r\n ring.isSpiro = true;\r\n neighbour.isSpiro = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n\r\n // Get the vector pointing from the shared vertex to the new centpositioner\r\n let nextCenter = Vector2.subtract(center, vertexA.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n // Get the distance from the vertex to the center\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertexA.position);\r\n\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA);\r\n }\r\n }\r\n }\r\n\r\n // Next, draw atoms that are not part of a ring that are directly attached to this ring\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let ringMember = this.graph.vertices[ring.members[i]];\r\n let ringMemberNeighbours = ringMember.neighbours;\r\n\r\n // If there are multiple, the ovlerap will be resolved in the appropriate step\r\n for (let j = 0; j < ringMemberNeighbours.length; j++) {\r\n let v = this.graph.vertices[ringMemberNeighbours[j]];\r\n\r\n if (v.positioned) {\r\n continue;\r\n }\r\n\r\n v.value.isConnectedToRing = true;\r\n this.createNextBond(v, ringMember, 0.0);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Rotate an entire subtree by an angle around a center.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree that is to rotate.\r\n * @param {Number} angle An angle in randians.\r\n * @param {Vector2} center The rotational center.\r\n */\r\n rotateSubtree(vertexId, parentVertexId, angle, center) {\r\n let that = this;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n vertex.position.rotateAround(angle, center);\r\n\r\n for (var i = 0; i < vertex.value.anchoredRings.length; i++) {\r\n let ring = that.rings[vertex.value.anchoredRings[i]];\r\n\r\n if (ring) {\r\n ring.center.rotateAround(angle, center);\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Gets the overlap score of a subtree.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree.\r\n * @param {Number[]} vertexOverlapScores An array containing the vertex overlap scores indexed by vertex id.\r\n * @returns {Object} An object containing the total overlap score and the center of mass of the subtree weighted by overlap score { value: 0.2, center: new Vector2() }.\r\n */\r\n getSubtreeOverlapScore(vertexId, parentVertexId, vertexOverlapScores) {\r\n let that = this;\r\n let score = 0;\r\n let center = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n if (!vertex.value.isDrawn) {\r\n return;\r\n }\r\n\r\n let s = vertexOverlapScores[vertex.id];\r\n if (s > that.opts.overlapSensitivity) {\r\n score += s;\r\n count++;\r\n }\r\n\r\n let position = that.graph.vertices[vertex.id].position.clone();\r\n position.multiplyScalar(s);\r\n center.add(position);\r\n });\r\n\r\n center.divide(score);\r\n\r\n return {\r\n value: score / count,\r\n center: center\r\n };\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass.\r\n *\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMass() {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass in the neighbourhood of a given position.\r\n *\r\n * @param {Vector2} vec The point at which to look for neighbours.\r\n * @param {Number} [r=currentBondLength*2.0] The radius of vertices to include.\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMassInNeigbourhood(vec, r = this.opts.bondLength * 2.0) {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n let rSq = r * r;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned && vec.distanceSq(vertex.position) < rSq) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Resolve primary (exact) overlaps, such as two vertices that are connected to the same ring vertex.\r\n */\r\n resolvePrimaryOverlaps() {\r\n let overlaps = Array();\r\n let done = Array(this.graph.vertices.length);\r\n\r\n // Looking for overlaps created by two bonds coming out of a ring atom, which both point straight\r\n // away from the ring and are thus perfectly overlapping.\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n let vertex = this.graph.vertices[ring.members[j]];\r\n\r\n if (done[vertex.id]) {\r\n continue;\r\n }\r\n\r\n done[vertex.id] = true;\r\n\r\n let nonRingNeighbours = this.getNonRingNeighbours(vertex.id);\r\n\r\n if (nonRingNeighbours.length > 1) {\r\n // Look for rings where there are atoms with two bonds outside the ring (overlaps)\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n } else if (nonRingNeighbours.length === 1 && vertex.value.rings.length === 2) {\r\n // Look for bonds coming out of joined rings to adjust the angle, an example is: C1=CC(=CC=C1)[C@]12SCCN1CC1=CC=CC=C21\r\n // where the angle has to be adjusted to account for fused ring\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (let i = 0; i < overlaps.length; i++) {\r\n let overlap = overlaps[i];\r\n\r\n if (overlap.vertices.length === 2) {\r\n let a = overlap.vertices[0];\r\n let b = overlap.vertices[1];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let angle = (2 * Math.PI - this.getRing(overlap.rings[0]).getAngle()) / 6.0;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -angle, overlap.common.position);\r\n\r\n // Decide which way to rotate the vertices depending on the effect it has on the overlap score\r\n let overlapScore = this.getOverlapScore();\r\n let subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n let subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n let total = subTreeOverlapA.value + subTreeOverlapB.value;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n\r\n overlapScore = this.getOverlapScore();\r\n subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n\r\n if (subTreeOverlapA.value + subTreeOverlapB.value > total) {\r\n this.rotateSubtree(a.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n }\r\n } else if (overlap.vertices.length === 1) {\r\n if (overlap.rings.length === 2) {\r\n // TODO: Implement for more overlap resolution\r\n // console.log(overlap);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resolve secondary overlaps. Those overlaps are due to the structure turning back on itself.\r\n *\r\n * @param {Object[]} scores An array of objects sorted descending by score.\r\n * @param {Number} scores[].id A vertex id.\r\n * @param {Number} scores[].score The overlap score associated with the vertex id.\r\n */\r\n resolveSecondaryOverlaps(scores) {\r\n for (let i = 0; i < scores.length; i++) {\r\n if (scores[i].score > this.opts.overlapSensitivity) {\r\n let vertex = this.graph.vertices[scores[i].id];\r\n\r\n if (vertex.isTerminal()) {\r\n let closest = this.getClosestVertex(vertex);\r\n\r\n if (closest) {\r\n // If one of the vertices is the first one, the previous vertex is not the central vertex but the dummy\r\n // so take the next rather than the previous, which is vertex 1\r\n let closestPosition = null;\r\n\r\n if (closest.isTerminal()) {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.previousPosition\r\n } else {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.position\r\n }\r\n\r\n let vertexPreviousPosition = vertex.id === 0 ? this.graph.vertices[1].position : vertex.previousPosition;\r\n\r\n vertex.position.rotateAwayFrom(closestPosition, vertexPreviousPosition, MathHelper.toRad(20));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the last non-null or 0 angle vertex.\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex} The last vertex with an angle that was not 0 or null.\r\n */\r\n getLastVertexWithAngle(vertexId) {\r\n let angle = 0;\r\n let vertex = null;\r\n\r\n while (!angle && vertexId) {\r\n vertex = this.graph.vertices[vertexId];\r\n angle = vertex.angle;\r\n vertexId = vertex.parentVertexId;\r\n }\r\n\r\n return vertex;\r\n }\r\n\r\n /**\r\n * Positiones the next vertex thus creating a bond.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @param {Vertex} [previousVertex=null] The previous vertex which has been positioned.\r\n * @param {Number} [angle=0.0] The (global) angle of the vertex.\r\n * @param {Boolean} [originShortest=false] Whether the origin is the shortest subtree in the branch.\r\n * @param {Boolean} [skipPositioning=false] Whether or not to skip positioning and just check the neighbours.\r\n */\r\n createNextBond(vertex, previousVertex = null, angle = 0.0, originShortest = false, skipPositioning = false) {\r\n if (vertex.positioned && !skipPositioning) {\r\n return;\r\n }\r\n\r\n // If the double bond config was set on this vertex, do not check later\r\n let doubleBondConfigSet = false;\r\n\r\n // Keeping track of configurations around double bonds\r\n if (previousVertex) {\r\n let edge = this.graph.getEdge(vertex.id, previousVertex.id);\r\n\r\n if ((edge.bondType === '/' || edge.bondType === '\\\\') && ++this.doubleBondConfigCount % 2 === 1) {\r\n if (this.doubleBondConfig === null) {\r\n this.doubleBondConfig = edge.bondType;\r\n doubleBondConfigSet = true;\r\n\r\n // Switch if the bond is a branch bond and previous vertex is the first\r\n // TODO: Why is it different with the first vertex?\r\n if (previousVertex.parentVertexId === null && vertex.value.branchBond) {\r\n if (this.doubleBondConfig === '/') {\r\n this.doubleBondConfig = '\\\\';\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n this.doubleBondConfig = '/';\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If the current node is the member of one ring, then point straight away\r\n // from the center of the ring. However, if the current node is a member of\r\n // two rings, point away from the middle of the centers of the two rings\r\n if (!skipPositioning) {\r\n if (!previousVertex) {\r\n // Add a (dummy) previous position if there is no previous vertex defined\r\n // Since the first vertex is at (0, 0), create a vector at (bondLength, 0)\r\n // and rotate it by 90°\r\n\r\n let dummy = new Vector2(this.opts.bondLength, 0);\r\n dummy.rotate(MathHelper.toRad(-60));\r\n\r\n vertex.previousPosition = dummy;\r\n vertex.setPosition(this.opts.bondLength, 0);\r\n vertex.angle = MathHelper.toRad(-60);\r\n\r\n // Do not position the vertex if it belongs to a bridged ring that is positioned using a layout algorithm.\r\n if (vertex.value.bridgedRing === null) {\r\n vertex.positioned = true;\r\n }\r\n } else if (previousVertex.value.rings.length > 0) {\r\n let neighbours = previousVertex.neighbours;\r\n let joinedVertex = null;\r\n let pos = new Vector2(0.0, 0.0);\r\n\r\n if (previousVertex.value.bridgedRing === null && previousVertex.value.rings.length > 1) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n if (ArrayHelper.containsAll(neighbour.value.rings, previousVertex.value.rings)) {\r\n joinedVertex = neighbour;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (joinedVertex === null) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let v = this.graph.vertices[neighbours[i]];\r\n\r\n if (v.positioned && this.areVerticesInSameRing(v, previousVertex)) {\r\n pos.add(Vector2.subtract(v.position, previousVertex.position));\r\n }\r\n }\r\n\r\n pos.invert().normalize().multiplyScalar(this.opts.bondLength).add(previousVertex.position);\r\n } else {\r\n pos = joinedVertex.position.clone().rotateAround(Math.PI, previousVertex.position);\r\n }\r\n\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.setPositionFromVector(pos);\r\n vertex.positioned = true;\r\n } else {\r\n // If the previous vertex was not part of a ring, draw a bond based\r\n // on the global angle of the previous bond\r\n let v = new Vector2(this.opts.bondLength, 0);\r\n\r\n v.rotate(angle);\r\n v.add(previousVertex.position);\r\n\r\n vertex.setPositionFromVector(v);\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.positioned = true;\r\n }\r\n }\r\n\r\n // Go to next vertex\r\n // If two rings are connected by a bond ...\r\n if (vertex.value.bridgedRing !== null) {\r\n let nextRing = this.getRing(vertex.value.bridgedRing);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.members.length);\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else if (vertex.value.rings.length > 0) {\r\n let nextRing = this.getRing(vertex.value.rings[0]);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else {\r\n // Draw the non-ring vertices connected to this one\r\n let isStereoCenter = vertex.value.isStereoCenter;\r\n let tmpNeighbours = vertex.getNeighbours();\r\n let neighbours = Array();\r\n\r\n // Remove neighbours that are not drawn\r\n for (let i = 0; i < tmpNeighbours.length; i++) {\r\n if (this.graph.vertices[tmpNeighbours[i]].value.isDrawn) {\r\n neighbours.push(tmpNeighbours[i]);\r\n }\r\n }\r\n\r\n // Remove the previous vertex (which has already been drawn)\r\n if (previousVertex) {\r\n neighbours = ArrayHelper.remove(neighbours, previousVertex.id);\r\n }\r\n\r\n let previousAngle = vertex.getAngle();\r\n\r\n if (neighbours.length === 1) {\r\n let nextVertex = this.graph.vertices[neighbours[0]];\r\n\r\n // Make a single chain always cis except when there's a tribble (yes, this is a Star Trek reference) bond\r\n // or if there are successive double bonds. Added a ring check because if there is an aromatic ring the ring bond inside the ring counts as a double bond and leads to =-= being straight.\r\n if ((vertex.value.bondType === '#' || (previousVertex && previousVertex.value.bondType === '#')) ||\r\n vertex.value.bondType === '=' && previousVertex && previousVertex.value.rings.length === 0 &&\r\n previousVertex.value.bondType === '=' && vertex.value.branchBond !== '-') {\r\n vertex.value.drawExplicit = false;\r\n\r\n if (previousVertex) {\r\n let straightEdge1 = this.graph.getEdge(vertex.id, previousVertex.id);\r\n straightEdge1.center = true;\r\n }\r\n\r\n let straightEdge2 = this.graph.getEdge(vertex.id, nextVertex.id);\r\n straightEdge2.center = true;\r\n\r\n if (vertex.value.bondType === '#' || previousVertex && previousVertex.value.bondType === '#') {\r\n nextVertex.angle = 0.0;\r\n }\r\n\r\n nextVertex.drawExplicit = true;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else if (previousVertex && previousVertex.value.rings.length > 0) {\r\n // If coming out of a ring, always draw away from the center of mass\r\n let proposedAngleA = MathHelper.toRad(60);\r\n let proposedAngleB = -proposedAngleA;\r\n\r\n let proposedVectorA = new Vector2(this.opts.bondLength, 0);\r\n let proposedVectorB = new Vector2(this.opts.bondLength, 0);\r\n\r\n proposedVectorA.rotate(proposedAngleA).add(vertex.position);\r\n proposedVectorB.rotate(proposedAngleB).add(vertex.position);\r\n\r\n // let centerOfMass = this.getCurrentCenterOfMassInNeigbourhood(vertex.position, 100);\r\n let centerOfMass = this.getCurrentCenterOfMass();\r\n let distanceA = proposedVectorA.distanceSq(centerOfMass);\r\n let distanceB = proposedVectorB.distanceSq(centerOfMass);\r\n\r\n nextVertex.angle = distanceA < distanceB ? proposedAngleB : proposedAngleA;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else {\r\n let a = vertex.angle;\r\n // Take the min and max if the previous angle was in a 4-neighbourhood (90° angles)\r\n // TODO: If a is null or zero, it should be checked whether or not this one should go cis or trans, that is,\r\n // it should go into the oposite direction of the last non-null or 0 previous vertex / angle.\r\n if (previousVertex && previousVertex.neighbours.length > 3) {\r\n if (a > 0) {\r\n a = Math.min(1.0472, a);\r\n } else if (a < 0) {\r\n a = Math.max(-1.0472, a);\r\n } else {\r\n a = 1.0472;\r\n }\r\n } else if (!a) {\r\n let v = this.getLastVertexWithAngle(vertex.id);\r\n a = v.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n }\r\n\r\n // Handle configuration around double bonds\r\n if (previousVertex && !doubleBondConfigSet) {\r\n let bondType = this.graph.getEdge(vertex.id, nextVertex.id).bondType;\r\n\r\n if (bondType === '/') {\r\n if (this.doubleBondConfig === '/') {\r\n // Nothing to do since it will be trans per default\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n a = -a;\r\n }\r\n this.doubleBondConfig = null;\r\n } else if (bondType === '\\\\') {\r\n if (this.doubleBondConfig === '/') {\r\n a = -a;\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n // Nothing to do since it will be trans per default\r\n }\r\n this.doubleBondConfig = null;\r\n }\r\n }\r\n\r\n if (originShortest) {\r\n nextVertex.angle = a;\r\n } else {\r\n nextVertex.angle = -a;\r\n }\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n }\r\n } else if (neighbours.length === 2) {\r\n // If the previous vertex comes out of a ring, it doesn't have an angle set\r\n let a = vertex.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n\r\n // Check for the longer subtree - always go with cis for the longer subtree\r\n let subTreeDepthA = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let subTreeDepthB = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n\r\n let l = this.graph.vertices[neighbours[0]];\r\n let r = this.graph.vertices[neighbours[1]];\r\n\r\n l.value.subtreeDepth = subTreeDepthA;\r\n r.value.subtreeDepth = subTreeDepthB;\r\n\r\n // Also get the subtree for the previous direction (this is important when\r\n // the previous vertex is the shortest path)\r\n let subTreeDepthC = this.graph.getTreeDepth(previousVertex ? previousVertex.id : null, vertex.id);\r\n if (previousVertex) {\r\n previousVertex.value.subtreeDepth = subTreeDepthC;\r\n }\r\n\r\n let cis = 0;\r\n let trans = 1;\r\n\r\n // Carbons go always cis\r\n if (r.value.element === 'C' && l.value.element !== 'C' && subTreeDepthB > 1 && subTreeDepthA < 5) {\r\n cis = 1;\r\n trans = 0;\r\n } else if (r.value.element !== 'C' && l.value.element === 'C' && subTreeDepthA > 1 && subTreeDepthB < 5) {\r\n cis = 0;\r\n trans = 1;\r\n } else if (subTreeDepthB > subTreeDepthA) {\r\n cis = 1;\r\n trans = 0;\r\n }\r\n\r\n let cisVertex = this.graph.vertices[neighbours[cis]];\r\n let transVertex = this.graph.vertices[neighbours[trans]];\r\n\r\n // If the origin tree is the shortest, make them the main chain\r\n let originShortest = false;\r\n if (subTreeDepthC < subTreeDepthA && subTreeDepthC < subTreeDepthB) {\r\n originShortest = true;\r\n }\r\n\r\n transVertex.angle = a;\r\n cisVertex.angle = -a;\r\n\r\n if (this.doubleBondConfig === '\\\\') {\r\n if (transVertex.value.branchBond === '\\\\') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n } else if (this.doubleBondConfig === '/') {\r\n if (transVertex.value.branchBond === '/') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n }\r\n\r\n this.createNextBond(transVertex, vertex, previousAngle + transVertex.angle, originShortest);\r\n this.createNextBond(cisVertex, vertex, previousAngle + cisVertex.angle, originShortest);\r\n } else if (neighbours.length === 3) {\r\n // The vertex with the longest sub-tree should always go straight\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n\r\n let s = this.graph.vertices[neighbours[0]];\r\n let l = this.graph.vertices[neighbours[1]];\r\n let r = this.graph.vertices[neighbours[2]];\r\n\r\n s.value.subtreeDepth = d1;\r\n l.value.subtreeDepth = d2;\r\n r.value.subtreeDepth = d3;\r\n\r\n if (d2 > d1 && d2 > d3) {\r\n s = this.graph.vertices[neighbours[1]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[2]];\r\n } else if (d3 > d1 && d3 > d2) {\r\n s = this.graph.vertices[neighbours[2]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[1]];\r\n }\r\n\r\n // Create a cross if more than one subtree is of length > 1\r\n // or the vertex is connected to a ring\r\n if (previousVertex &&\r\n previousVertex.value.rings.length < 1 &&\r\n s.value.rings.length < 1 &&\r\n l.value.rings.length < 1 &&\r\n r.value.rings.length < 1 &&\r\n this.graph.getTreeDepth(l.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(r.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(s.id, vertex.id) > 1) {\r\n\r\n s.angle = -vertex.angle;\r\n if (vertex.angle >= 0) {\r\n l.angle = MathHelper.toRad(30);\r\n r.angle = MathHelper.toRad(90);\r\n } else {\r\n l.angle = -MathHelper.toRad(30);\r\n r.angle = -MathHelper.toRad(90);\r\n }\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n } else {\r\n s.angle = 0.0;\r\n l.angle = MathHelper.toRad(90);\r\n r.angle = -MathHelper.toRad(90);\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n }\r\n } else if (neighbours.length === 4) {\r\n // The vertex with the longest sub-tree should always go to the reflected opposide direction\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n let d4 = this.graph.getTreeDepth(neighbours[3], vertex.id);\r\n\r\n let w = this.graph.vertices[neighbours[0]];\r\n let x = this.graph.vertices[neighbours[1]];\r\n let y = this.graph.vertices[neighbours[2]];\r\n let z = this.graph.vertices[neighbours[3]];\r\n\r\n w.value.subtreeDepth = d1;\r\n x.value.subtreeDepth = d2;\r\n y.value.subtreeDepth = d3;\r\n z.value.subtreeDepth = d4;\r\n\r\n if (d2 > d1 && d2 > d3 && d2 > d4) {\r\n w = this.graph.vertices[neighbours[1]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[2]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d3 > d1 && d3 > d2 && d3 > d4) {\r\n w = this.graph.vertices[neighbours[2]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d4 > d1 && d4 > d2 && d4 > d3) {\r\n w = this.graph.vertices[neighbours[3]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[2]];\r\n }\r\n\r\n w.angle = -MathHelper.toRad(36);\r\n x.angle = MathHelper.toRad(36);\r\n y.angle = -MathHelper.toRad(108);\r\n z.angle = MathHelper.toRad(108);\r\n\r\n this.createNextBond(w, vertex, previousAngle + w.angle);\r\n this.createNextBond(x, vertex, previousAngle + x.angle);\r\n this.createNextBond(y, vertex, previousAngle + y.angle);\r\n this.createNextBond(z, vertex, previousAngle + z.angle);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Gets the vetex sharing the edge that is the common bond of two rings.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {(Number|null)} The id of a vertex sharing the edge that is the common bond of two rings with the vertex provided or null, if none.\r\n */\r\n getCommonRingbondNeighbour(vertex) {\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n\r\n if (ArrayHelper.containsAll(neighbour.value.rings, vertex.value.rings)) {\r\n return neighbour;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Check if a vector is inside any ring.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Boolean} A boolean indicating whether or not the point (vector) is inside any of the rings associated with the current molecule.\r\n */\r\n isPointInRing(vec) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (!ring.positioned) {\r\n continue;\r\n }\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let radiusSq = radius * radius;\r\n\r\n if (vec.distanceSq(ring.center) < radiusSq) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is part of a ring.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is part of a ring.\r\n */\r\n isEdgeInRing(edge) {\r\n let source = this.graph.vertices[edge.sourceId];\r\n let target = this.graph.vertices[edge.targetId];\r\n\r\n return this.areVerticesInSameRing(source, target);\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is rotatable.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is rotatable.\r\n */\r\n isEdgeRotatable(edge) {\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n\r\n // Only single bonds are rotatable\r\n if (edge.bondType !== '-') {\r\n return false;\r\n }\r\n\r\n // Do not rotate edges that have a further single bond to each side - do that!\r\n // If the bond is terminal, it doesn't make sense to rotate it\r\n // if (vertexA.getNeighbourCount() + vertexB.getNeighbourCount() < 5) {\r\n // return false;\r\n // }\r\n\r\n if (vertexA.isTerminal() || vertexB.isTerminal()) {\r\n return false;\r\n }\r\n\r\n // Ringbonds are not rotatable\r\n return !(vertexA.value.rings.length > 0 && vertexB.value.rings.length > 0 && this.areVerticesInSameRing(vertexA, vertexB));\r\n }\r\n\r\n /**\r\n * Check whether or not a ring is an implicitly defined aromatic ring (lower case smiles).\r\n *\r\n * @param {Ring} ring A ring.\r\n * @returns {Boolean} A boolean indicating whether or not a ring is implicitly defined as aromatic.\r\n */\r\n isRingAromatic(ring) {\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let vertex = this.graph.vertices[ring.members[i]];\r\n\r\n if (!vertex.value.isPartOfAromaticRing) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the normals of an edge.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Vector2[]} An array containing two vectors, representing the normals.\r\n */\r\n getEdgeNormals(edge) {\r\n let v1 = this.graph.vertices[edge.sourceId].position;\r\n let v2 = this.graph.vertices[edge.targetId].position;\r\n\r\n // Get the normalized normals for the edge\r\n return Vector2.units(v1, v2);\r\n }\r\n\r\n /**\r\n * Returns an array of vertices that are neighbouring a vertix but are not members of a ring (including bridges).\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex[]} An array of vertices.\r\n */\r\n getNonRingNeighbours(vertexId) {\r\n let nrneighbours = Array();\r\n let vertex = this.graph.vertices[vertexId];\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n let nIntersections = ArrayHelper.intersection(vertex.value.rings, neighbour.value.rings).length;\r\n\r\n if (nIntersections === 0 && neighbour.value.isBridge == false) {\r\n nrneighbours.push(neighbour);\r\n }\r\n }\r\n\r\n return nrneighbours;\r\n }\r\n\r\n /**\r\n * Annotaed stereochemistry information for visualization.\r\n */\r\n annotateStereochemistry() {\r\n let maxDepth = 10;\r\n\r\n // For each stereo-center\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (!vertex.value.isStereoCenter) {\r\n continue;\r\n }\r\n\r\n let neighbours = vertex.getNeighbours();\r\n let nNeighbours = neighbours.length;\r\n let priorities = Array(nNeighbours);\r\n\r\n for (let j = 0; j < nNeighbours; j++) {\r\n let visited = new Uint8Array(this.graph.vertices.length);\r\n let priority = Array(Array());\r\n visited[vertex.id] = 1;\r\n\r\n this.visitStereochemistry(neighbours[j], vertex.id, visited, priority, maxDepth, 0);\r\n\r\n // Sort each level according to atomic number\r\n for (let k = 0; k < priority.length; k++) {\r\n priority[k].sort(function (a, b) {\r\n return b - a\r\n });\r\n }\r\n\r\n priorities[j] = [j, priority];\r\n }\r\n\r\n let maxLevels = 0;\r\n let maxEntries = 0;\r\n for (let j = 0; j < priorities.length; j++) {\r\n if (priorities[j][1].length > maxLevels) {\r\n maxLevels = priorities[j][1].length;\r\n }\r\n\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n if (priorities[j][1][k].length > maxEntries) {\r\n maxEntries = priorities[j][1][k].length;\r\n }\r\n }\r\n }\r\n\r\n for (let j = 0; j < priorities.length; j++) {\r\n let diff = maxLevels - priorities[j][1].length;\r\n for (let k = 0; k < diff; k++) {\r\n priorities[j][1].push([]);\r\n }\r\n\r\n // Break ties by the position in the SMILES string as per specification\r\n priorities[j][1].push([neighbours[j]]);\r\n\r\n // Make all same length. Fill with zeroes.\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n let diff = maxEntries - priorities[j][1][k].length;\r\n\r\n for (let l = 0; l < diff; l++) {\r\n priorities[j][1][k].push(0);\r\n }\r\n }\r\n }\r\n\r\n priorities.sort(function (a, b) {\r\n for (let j = 0; j < a[1].length; j++) {\r\n for (let k = 0; k < a[1][j].length; k++) {\r\n if (a[1][j][k] > b[1][j][k]) {\r\n return -1;\r\n } else if (a[1][j][k] < b[1][j][k]) {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n\r\n let order = new Uint8Array(nNeighbours);\r\n for (let j = 0; j < nNeighbours; j++) {\r\n order[j] = priorities[j][0];\r\n vertex.value.priority = j;\r\n }\r\n\r\n // Check the angles between elements 0 and 1, and 0 and 2 to determine whether they are\r\n // drawn cw or ccw\r\n // TODO: OC(Cl)=[C@]=C(C)F currently fails here, however this is, IMHO, not a valid SMILES.\r\n let posA = this.graph.vertices[neighbours[order[0]]].position;\r\n let posB = this.graph.vertices[neighbours[order[1]]].position;\r\n\r\n let cwA = posA.relativeClockwise(posB, vertex.position);\r\n\r\n // If the second priority is clockwise from the first, the ligands are drawn clockwise, since\r\n // The hydrogen can be drawn on either side\r\n let isCw = cwA === -1;\r\n\r\n let rotation = vertex.value.bracket.chirality === '@' ? -1 : 1;\r\n let rs = MathHelper.parityOfPermutation(order) * rotation === 1 ? 'R' : 'S';\r\n\r\n // Flip the hydrogen direction when the drawing doesn't match the chirality.\r\n let wedgeA = 'down';\r\n let wedgeB = 'up';\r\n if (isCw && rs !== 'R' || !isCw && rs !== 'S') {\r\n vertex.value.hydrogenDirection = 'up';\r\n wedgeA = 'up';\r\n wedgeB = 'down';\r\n }\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, neighbours[order[order.length - 1]]).wedge = wedgeA;\r\n }\r\n\r\n // Get the shortest subtree to flip up / down. Ignore lowest priority\r\n // The rules are following:\r\n // 1. Do not draw wedge between two stereocenters\r\n // 2. Heteroatoms\r\n // 3. Draw outside ring\r\n // 4. Shortest subtree\r\n\r\n let wedgeOrder = new Array(neighbours.length - 1);\r\n let showHydrogen = vertex.value.rings.length > 1 && vertex.value.hasHydrogen;\r\n let offset = vertex.value.hasHydrogen ? 1 : 0;\r\n\r\n for (let j = 0; j < order.length - offset; j++) {\r\n wedgeOrder[j] = new Uint32Array(2);\r\n let neighbour = this.graph.vertices[neighbours[order[j]]];\r\n wedgeOrder[j][0] += neighbour.value.isStereoCenter ? 0 : 100000;\r\n // wedgeOrder[j][0] += neighbour.value.rings.length > 0 ? 0 : 10000;\r\n // Only add if in same ring, unlike above\r\n wedgeOrder[j][0] += this.areVerticesInSameRing(neighbour, vertex) ? 0 : 10000;\r\n wedgeOrder[j][0] += neighbour.value.isHeteroAtom() ? 1000 : 0;\r\n wedgeOrder[j][0] -= neighbour.value.subtreeDepth === 0 ? 1000 : 0;\r\n wedgeOrder[j][0] += 1000 - neighbour.value.subtreeDepth;\r\n wedgeOrder[j][1] = neighbours[order[j]];\r\n }\r\n\r\n\r\n wedgeOrder.sort(function (a, b) {\r\n if (a[0] > b[0]) {\r\n return -1;\r\n } else if (a[0] < b[0]) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n\r\n // If all neighbours are in a ring, do not draw wedge, the hydrogen will be drawn.\r\n if (!showHydrogen) {\r\n let wedgeId = wedgeOrder[0][1];\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedgeB;\r\n } else {\r\n let wedge = wedgeB;\r\n\r\n for (let j = order.length - 1; j >= 0; j--) {\r\n if (wedge === wedgeA) {\r\n wedge = wedgeB;\r\n } else {\r\n wedge = wedgeA;\r\n }\r\n if (neighbours[order[j]] === wedgeId) {\r\n break;\r\n }\r\n }\r\n\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedge;\r\n }\r\n }\r\n\r\n vertex.value.chirality = rs;\r\n }\r\n }\r\n\r\n /**\r\n *\r\n *\r\n * @param {Number} vertexId The id of a vertex.\r\n * @param {(Number|null)} previousVertexId The id of the parent vertex of the vertex.\r\n * @param {Uint8Array} visited An array containing the visited flag for all vertices in the graph.\r\n * @param {Array} priority An array of arrays storing the atomic numbers for each level.\r\n * @param {Number} maxDepth The maximum depth.\r\n * @param {Number} depth The current depth.\r\n * @param {Number} parentAtomicNumber\r\n */\r\n visitStereochemistry(vertexId, previousVertexId, visited, priority, maxDepth, depth, parentAtomicNumber = 0) {\r\n visited[vertexId] = 1;\r\n let vertex = this.graph.vertices[vertexId];\r\n let atomicNumber = vertex.value.getAtomicNumber();\r\n\r\n if (priority.length <= depth) {\r\n priority.push(Array());\r\n }\r\n\r\n for (let i = 0; i < this.graph.getEdge(vertexId, previousVertexId).weight; i++) {\r\n priority[depth].push(parentAtomicNumber * 1000 + atomicNumber);\r\n }\r\n\r\n let neighbours = this.graph.vertices[vertexId].neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (visited[neighbours[i]] !== 1 && depth < maxDepth - 1) {\r\n this.visitStereochemistry(neighbours[i], vertexId, visited.slice(), priority, maxDepth, depth + 1, atomicNumber);\r\n }\r\n }\r\n\r\n // Valences are filled with hydrogens and passed to the next level.\r\n if (depth < maxDepth - 1) {\r\n let bonds = 0;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n bonds += this.graph.getEdge(vertexId, neighbours[i]).weight;\r\n }\r\n\r\n for (let i = 0; i < vertex.value.getMaxBonds() - bonds; i++) {\r\n if (priority.length <= depth + 1) {\r\n priority.push(Array());\r\n }\r\n\r\n priority[depth + 1].push(atomicNumber * 1000 + 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Creates pseudo-elements (such as Et, Me, Ac, Bz, ...) at the position of the carbon sets\r\n * the involved atoms not to be displayed.\r\n */\r\n initPseudoElements() {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n // Ignore atoms that have less than 3 neighbours, except if\r\n // the vertex is connected to a ring and has two neighbours\r\n if (vertex.getNeighbourCount() < 3 || vertex.value.rings.length > 0) {\r\n continue;\r\n }\r\n\r\n // TODO: This exceptions should be handled more elegantly (via config file?)\r\n\r\n // Ignore phosphates (especially for triphosphates)\r\n if (vertex.value.element === 'P') {\r\n continue;\r\n }\r\n\r\n // Ignore also guanidine\r\n if (vertex.value.element === 'C' && neighbours.length === 3 &&\r\n neighbours[0].value.element === 'N' && neighbours[1].value.element === 'N' && neighbours[2].value.element === 'N') {\r\n continue;\r\n }\r\n\r\n // Continue if there are less than two heteroatoms\r\n // or if a neighbour has more than 1 neighbour\r\n let heteroAtomCount = 0;\r\n let ctn = 0;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n let neighbouringElement = neighbour.value.element;\r\n let neighbourCount = neighbour.getNeighbourCount();\r\n\r\n if (neighbouringElement !== 'C' && neighbouringElement !== 'H' &&\r\n neighbourCount === 1) {\r\n heteroAtomCount++;\r\n }\r\n\r\n if (neighbourCount > 1) {\r\n ctn++;\r\n }\r\n }\r\n\r\n if (ctn > 1 || heteroAtomCount < 2) {\r\n continue;\r\n }\r\n\r\n // Get the previous atom (the one which is not terminal)\r\n let previous = null;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n previous = neighbour;\r\n }\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n continue;\r\n }\r\n\r\n neighbour.value.isDrawn = false;\r\n\r\n let hydrogens = Atom.maxBonds[neighbour.value.element] - neighbour.value.bondCount;\r\n let charge = '';\r\n\r\n if (neighbour.value.bracket) {\r\n hydrogens = neighbour.value.bracket.hcount;\r\n charge = neighbour.value.bracket.charge || 0;\r\n }\r\n\r\n vertex.value.attachPseudoElement(neighbour.value.element, previous ? previous.value.element : null, hydrogens, charge);\r\n }\r\n }\r\n\r\n // The second pass\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const atom = vertex.value;\r\n const element = atom.element;\r\n\r\n if (element === 'C' || element === 'H' || !atom.isDrawn) {\r\n continue;\r\n }\r\n\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j].value;\r\n\r\n if (!neighbour.hasAttachedPseudoElements || neighbour.getAttachedPseudoElementsCount() !== 2) {\r\n continue;\r\n }\r\n\r\n const pseudoElements = neighbour.getAttachedPseudoElements();\r\n\r\n if (pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\r\n neighbour.isDrawn = false;\r\n vertex.value.attachPseudoElement('Ac', '', 0);\r\n }\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.graph.getDecays();\r\n }\r\n\r\n buildBlockSmiles() {\r\n return this.graph.buildSmiles();\r\n }\r\n\r\n /**\r\n * Find edge and mark it as decay point and redraw graph\r\n * @param e event\r\n */\r\n handleMouseClick(e) {\r\n if (this.opts.drawDecayPoints === DecayState.VALUES.NO) {\r\n return;\r\n }\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (!this.graph) {\r\n return;\r\n }\r\n this.findAndReDrawEdge(e.clientX - this.opts.offsetX, e.clientY - this.opts.offsetY + (document.documentElement.scrollTop || document.body.scrollTop));\r\n }\r\n\r\n /**\r\n * Find edge which was clicked, mark edge as decay point and redraw graph\r\n * @param mouseX mouse positionX - offsetX\r\n * @param mouseY mouse positionY - offsetY\r\n */\r\n findAndReDrawEdge(mouseX, mouseY) {\r\n for (let i = 0; i < this.graph.edges.length; ++i) {\r\n let vertexA = this.graph.vertices[this.graph.edges[i].sourceId];\r\n let vertexB = this.graph.vertices[this.graph.edges[i].targetId];\r\n if (!vertexA || !vertexB) {\r\n continue;\r\n }\r\n let scale = this.computeScale();\r\n let line = new Line(vertexA.position, vertexB.position, null, null, false, false, true);\r\n let l = this.computeEdgeLeftPoint(line, scale);\r\n let r = this.computeEdgeRightPoint(line, scale);\r\n if (mouseX < l.x - this.opts.mouseTolerance || mouseX > r.x + this.opts.mouseTolerance) {\r\n continue;\r\n }\r\n if ((mouseY > l.y - this.opts.mouseTolerance && mouseY < r.y + this.opts.mouseTolerance)\r\n || (mouseY > r.y - this.opts.mouseTolerance && mouseY < l.y + this.opts.mouseTolerance)) {\r\n this.reDrawGraphWithEdgeAsDecay(i);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Make edge decay point and redraw graph\r\n * @param {Number} edgeId\r\n */\r\n reDrawGraphWithEdgeAsDecay(edgeId) {\r\n this.graph.revertEdgeDecayPoint(edgeId);\r\n this.canvasWrapper.updateSize(this.opts.width, this.opts.height);\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n }\r\n\r\n /**\r\n * Compute scale of canvas\r\n * @return {number} scale\r\n */\r\n computeScale() {\r\n let scaleX = this.canvasWrapper.canvas.offsetWidth / this.canvasWrapper.drawingWidth;\r\n let scaleY = this.canvasWrapper.canvas.offsetHeight / this.canvasWrapper.drawingHeight;\r\n return (scaleX < scaleY) ? scaleX : scaleY;\r\n }\r\n\r\n /**\r\n * Compute left point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeLeftPoint(line, scale) {\r\n return this.computeEdgePoint(line.getLeftVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute right point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeRightPoint(line, scale) {\r\n return this.computeEdgePoint(line.getRightVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute point coordinates for compare\r\n * add offset to coordinates and multiply coordinates with scale\r\n * @param {Vector2} point\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgePoint(point, scale) {\r\n point.x += this.canvasWrapper.offsetX;\r\n point.y += this.canvasWrapper.offsetY;\r\n point.x *= scale;\r\n point.y *= scale;\r\n return point;\r\n }\r\n}\r\n\r\nmodule.exports = Drawer;\r\n","//@ts-check\r\n\r\n/** \r\n * A class representing an edge. \r\n * \r\n * @property {Number} id The id of this edge.\r\n * @property {Number} sourceId The id of the source vertex.\r\n * @property {Number} targetId The id of the target vertex.\r\n * @property {Number} weight The weight of this edge. That is, the degree of the bond (single bond = 1, double bond = 2, etc).\r\n * @property {String} [bondType='-'] The bond type of this edge.\r\n * @property {Boolean} [isPartOfAromaticRing=false] Whether or not this edge is part of an aromatic ring.\r\n * @property {Boolean} [center=false] Wheter or not the bond is centered. For example, this affects straight double bonds.\r\n * @property {String} [wedge=''] Wedge direction. Either '', 'up' or 'down'\r\n */\r\nclass Edge {\r\n /**\r\n * The constructor for the class Edge.\r\n *\r\n * @param {Number} sourceId A vertex id.\r\n * @param {Number} targetId A vertex id.\r\n * @param {Number} [weight=1] The weight of the edge.\r\n */\r\n constructor(sourceId, targetId, weight = 1) {\r\n this.id = null;\r\n this.sourceId = sourceId;\r\n this.targetId = targetId;\r\n this.weight = weight;\r\n this.bondType = '-';\r\n this.isPartOfAromaticRing = false;\r\n this.center = false;\r\n this.wedge = '';\r\n this.isDecay = false;\r\n this.isDecayAll = false;\r\n }\r\n\r\n /**\r\n * Set the bond type of this edge. This also sets the edge weight.\r\n * @param {String} bondType \r\n */\r\n setBondType(bondType) {\r\n this.bondType = bondType;\r\n this.weight = Edge.bonds[bondType];\r\n }\r\n\r\n /**\r\n * Set decay\r\n * @param {Boolean} decay point\r\n */\r\n setDecay(decay) {\r\n this.isDecay = decay;\r\n }\r\n\r\n /**\r\n * Set decay All\r\n * @param {Boolean} decay point\r\n */\r\n setDecayAll(decay) {\r\n this.isDecayAll = decay;\r\n }\r\n\r\n /**\r\n * An object mapping the bond type to the number of bonds.\r\n *\r\n * @returns {Object} The object containing the map.\r\n */\r\n static get bonds() {\r\n return {\r\n '-': 1,\r\n '/': 1,\r\n '\\\\': 1,\r\n '=': 2,\r\n '#': 3,\r\n '$': 4\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Edge;\r\n","//@ts-check\r\nconst DecayPoint = require('./DecayPoint');\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Ring = require('./Ring');\r\nconst Atom = require('./Atom');\r\nconst VertexState = require('./VertexState');\r\nconst SmallGraph = require('./SmallGraph');\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst DecayState = require('./DecayState');\r\nconst MutableBoolean = require('./MutableBoolean');\r\nconst MutableCounter = require('./MutableCounter');\r\nconst Direction = require('./Direction');\r\n\r\n/**\r\n * A class representing the molecular graph.\r\n *\r\n * @property {Vertex[]} vertices The vertices of the graph.\r\n * @property {Edge[]} edges The edges of this graph.\r\n * @property {Number[]} decays The id of edges marked as decay point of this graph.\r\n * @property {Object} vertexIdsToEdgeId A map mapping vertex ids to the edge between the two vertices. The key is defined as vertexAId + '_' + vertexBId.\r\n * @property {Boolean} isometric A boolean indicating whether or not the SMILES associated with this graph is isometric.\r\n */\r\nclass Graph {\r\n /**\r\n * The constructor of the class Graph.\r\n *\r\n * @param {Object} parseTree A SMILES parse tree.\r\n * @param {Boolean} [isomeric=false] A boolean specifying whether or not the SMILES is isomeric.\r\n * @param options\r\n */\r\n constructor(parseTree, isomeric = false, options = {}) {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.decays = Array();\r\n this.decaysAll = Array();\r\n this.vertexIdsToEdgeId = {};\r\n this.isomeric = isomeric;\r\n this._startingVertexes = [];\r\n this._isCyclic = false;\r\n this._polyketide = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.options = options;\r\n this._componentsIsPolyketide = [];\r\n\r\n // Used for the bridge detection algorithm\r\n this._time = 0;\r\n this._init(parseTree);\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION. Initializing the graph from the parse tree.\r\n *\r\n * @param {Object} node The current node in the parse tree.\r\n * @param order\r\n * @param {Number} parentVertexId=null The id of the previous vertex.\r\n * @param {Boolean} isBranch=false Whether or not the bond leading to this vertex is a branch bond. Branches are represented by parentheses in smiles (e.g. CC(O)C).\r\n */\r\n _init(node, order = 0, parentVertexId = null, isBranch = false) {\r\n // Create a new vertex object\r\n let atom = new Atom(node.atom.element ? node.atom.element : node.atom, node.bond);\r\n\r\n atom.branchBond = node.branchBond;\r\n atom.ringbonds = node.ringbonds;\r\n atom.bracket = node.atom.element ? node.atom : null;\r\n\r\n let vertex = new Vertex(atom);\r\n let parentVertex = this.vertices[parentVertexId];\r\n\r\n this.addVertex(vertex);\r\n\r\n // Add the id of this node to the parent as child\r\n if (parentVertexId !== null) {\r\n vertex.setParentVertexId(parentVertexId);\r\n vertex.value.addNeighbouringElement(parentVertex.value.element);\r\n parentVertex.addChild(vertex.id);\r\n parentVertex.value.addNeighbouringElement(atom.element);\r\n\r\n // In addition create a spanningTreeChildren property, which later will\r\n // not contain the children added through ringbonds\r\n parentVertex.spanningTreeChildren.push(vertex.id);\r\n\r\n // Add edge between this node and its parent\r\n let edge = new Edge(parentVertexId, vertex.id, 1);\r\n let vertexId;\r\n\r\n if (isBranch) {\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n } else {\r\n edge.setBondType(parentVertex.value.bondType || '-');\r\n vertexId = parentVertex.id;\r\n }\r\n\r\n this.addEdge(edge);\r\n }\r\n\r\n let offset = node.ringbondCount + 1;\r\n\r\n if (atom.bracket) {\r\n offset += atom.bracket.hcount;\r\n }\r\n\r\n let stereoHydrogens = 0;\r\n if (atom.bracket && atom.bracket.chirality) {\r\n atom.isStereoCenter = true;\r\n stereoHydrogens = atom.bracket.hcount;\r\n for (var i = 0; i < stereoHydrogens; i++) {\r\n this._init({\r\n atom: 'H',\r\n isBracket: 'false',\r\n branches: Array(),\r\n branchCount: 0,\r\n ringbonds: Array(),\r\n ringbondCount: false,\r\n next: null,\r\n hasNext: false,\r\n bond: '-'\r\n }, i, vertex.id, true);\r\n }\r\n }\r\n\r\n for (var i = 0; i < node.branchCount; i++) {\r\n this._init(node.branches[i], i + offset, vertex.id, true);\r\n }\r\n\r\n if (node.hasNext) {\r\n this._init(node.next, node.branchCount + offset, vertex.id);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of molecule\r\n * Types of decay points, declared in DecayPoint\r\n */\r\n findDecayPoints() {\r\n if (!Object.keys(this.options).length) {\r\n return;\r\n }\r\n\r\n switch (this.options.drawDecayPoints) {\r\n default:\r\n case DecayState.VALUES.NO:\r\n return;\r\n case DecayState.VALUES.STANDARD:\r\n this.standardDecays();\r\n break;\r\n case DecayState.VALUES.SOURCE:\r\n this.sourceDecays();\r\n break;\r\n case DecayState.VALUES.STANDARD_AND_SOURCE:\r\n this.standardDecays();\r\n this.sourceDecays();\r\n break;\r\n }\r\n }\r\n\r\n reduceDecays() {\r\n this._decaysCopy = [];\r\n this.dfsSmilesInitialization();\r\n for (let i = 0; i < this.decays.length; i++) {\r\n this.smallBlockDfsStart(this.edges[this.decays[i]]);\r\n }\r\n this.decays = [];\r\n this.decays = this._decaysCopy;\r\n this.setStandardDecays();\r\n }\r\n\r\n dfsSmallInitialization(vertices) {\r\n for (let i = 0; i < vertices.length; ++i) {\r\n this.vertices[vertices[i]].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n smallBlockDfsStart(edge) {\r\n let stackVisitedVertexes = [];\r\n let depth = this.smallDfs(this.vertices[edge.sourceId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n stackVisitedVertexes = [];\r\n depth = this.smallDfs(this.vertices[edge.targetId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n this._decaysCopy.push(edge.id);\r\n }\r\n }\r\n }\r\n\r\n smallDfs(vertex, depth, stackVisitedVertexes) {\r\n stackVisitedVertexes.push(vertex.id);\r\n if (depth > 3) {\r\n return depth;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return depth;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n ++depth;\r\n\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n depth = this.smallDfs(this.vertices[nextVertex], depth, stackVisitedVertexes);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n return depth;\r\n }\r\n\r\n setStandardDecays() {\r\n this.edges.forEach(e => {\r\n e.setDecay(false);\r\n });\r\n this.decays.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n });\r\n }\r\n\r\n standardDecays() {\r\n for (let i = 0; i < this.edges.length; i++) {\r\n if (this.edges[i].bondType === '=') {\r\n let dec = this.isDecayPoint(this.edges[i].sourceId, this.edges[i].targetId, i);\r\n if (dec !== false) {\r\n this.edges[dec].setDecay(true);\r\n this.decays.push(dec);\r\n this.edges[dec].setDecayAll(true);\r\n this.decaysAll.push(dec);\r\n }\r\n }\r\n }\r\n this.reduceDecays();\r\n }\r\n\r\n sourceDecays() {\r\n this.options.decaySource.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n this.edges[e].setDecayAll(true);\r\n this.decays.push(e);\r\n this.decaysAll.push(e);\r\n });\r\n }\r\n\r\n /**\r\n * check if its decay point of specific decay types\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @param decayTypes DecayPoint\r\n * @returns {int|boolean} return edge id when found, otherwise return false\r\n */\r\n isDecayPoint(sourceId, targetId, edgeBondId, decayTypes = DecayPoint.VALUES.ALL) {\r\n switch (decayTypes) {\r\n case DecayPoint.VALUES.ALL:\r\n let found = this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n if (found === false) {\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n } else {\r\n return found;\r\n }\r\n case DecayPoint.VALUES.COO:\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n case DecayPoint.VALUES.CONH:\r\n return this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-O- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'O', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'O', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-NH- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'N', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'N', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay point edge id of right neighbour\r\n * @param vertexId\r\n * @param element\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayId(vertexId, element, edgeBondId) {\r\n for (let i = 0; i < this.vertices[vertexId].edges.length; i++) {\r\n let edgeId = this.checkNeighbourEdgeId(this.vertices[vertexId].edges[i], vertexId, element);\r\n if (edgeId !== false && edgeId !== edgeBondId) {\r\n return edgeId;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find edge id of decay point\r\n * @param edgeId\r\n * @param vertexId\r\n * @param element\r\n * @returns {int|boolean}\r\n */\r\n checkNeighbourEdgeId(edgeId, vertexId, element) {\r\n if ((this.edges[edgeId].sourceId === vertexId && this.vertices[this.edges[edgeId].targetId].value.element === element) ||\r\n (this.edges[edgeId].targetId === vertexId && this.vertices[this.edges[edgeId].sourceId].value.element === element)) {\r\n return edgeId;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clears all the elements in this graph (edges and vertices).\r\n */\r\n clear() {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.vertexIdsToEdgeId = {};\r\n }\r\n\r\n /**\r\n * Add a vertex to the graph.\r\n *\r\n * @param {Vertex} vertex A new vertex.\r\n * @returns {Number} The vertex id of the new vertex.\r\n */\r\n addVertex(vertex) {\r\n vertex.id = this.vertices.length;\r\n this.vertices.push(vertex);\r\n\r\n return vertex.id;\r\n }\r\n\r\n /**\r\n * Add an edge to the graph.\r\n *\r\n * @param {Edge} edge A new edge.\r\n * @returns {Number} The edge id of the new edge.\r\n */\r\n addEdge(edge) {\r\n let source = this.vertices[edge.sourceId];\r\n let target = this.vertices[edge.targetId];\r\n\r\n edge.id = this.edges.length;\r\n this.edges.push(edge);\r\n\r\n this.vertexIdsToEdgeId[edge.sourceId + '_' + edge.targetId] = edge.id;\r\n this.vertexIdsToEdgeId[edge.targetId + '_' + edge.sourceId] = edge.id;\r\n edge.isPartOfAromaticRing = source.value.isPartOfAromaticRing && target.value.isPartOfAromaticRing;\r\n\r\n source.value.bondCount += edge.weight;\r\n target.value.bondCount += edge.weight;\r\n\r\n source.edges.push(edge.id);\r\n target.edges.push(edge.id);\r\n\r\n return edge.id;\r\n }\r\n\r\n /**\r\n * Returns the edge between two given vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {(Edge|null)} The edge or, if no edge can be found, null.\r\n */\r\n getEdge(vertexIdA, vertexIdB) {\r\n let edgeId = this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB];\r\n\r\n return edgeId === undefined ? null : this.edges[edgeId];\r\n }\r\n\r\n /**\r\n * Returns the ids of edges connected to a vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Number[]} An array containing the ids of edges connected to the vertex.\r\n */\r\n getEdges(vertexId) {\r\n let edgeIds = Array();\r\n let vertex = this.vertices[vertexId];\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n edgeIds.push(this.vertexIdsToEdgeId[vertexId + '_' + vertex.neighbours[i]]);\r\n }\r\n\r\n return edgeIds;\r\n }\r\n\r\n\r\n /**\r\n * Check whether or not two vertices are connected by an edge.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not two vertices are connected by an edge.\r\n */\r\n hasEdge(vertexIdA, vertexIdB) {\r\n return this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB] !== undefined\r\n }\r\n\r\n /**\r\n * Returns an array containing the vertex ids of this graph.\r\n *\r\n * @returns {Number[]} An array containing all vertex ids of this graph.\r\n */\r\n getVertexList() {\r\n let arr = [this.vertices.length];\r\n\r\n for (var i = 0; i < this.vertices.length; i++) {\r\n arr[i] = this.vertices[i].id;\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array containing source, target arrays of this graphs edges.\r\n *\r\n * @returns {Array[]} An array containing source, target arrays of this graphs edges. Example: [ [ 2, 5 ], [ 6, 9 ] ].\r\n */\r\n getEdgeList() {\r\n let arr = Array(this.edges.length);\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n arr[i] = [this.edges[i].sourceId, this.edges[i].targetId];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph.\r\n */\r\n getAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph with all bridges removed (thus the components). Thus the remaining vertices are all part of ring systems.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph with all bridges removed.\r\n */\r\n getComponentsAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n let bridges = this.getBridges();\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n for (var i = 0; i < bridges.length; i++) {\r\n adjacencyMatrix[bridges[i][0]][bridges[i][1]] = 0;\r\n adjacencyMatrix[bridges[i][1]][bridges[i][0]] = 0;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency matrix of the subgraph.\r\n */\r\n getSubgraphAdjacencyMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyMatrix[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of the graph.\r\n *\r\n * @returns {Array[]} The distance matrix of the graph.\r\n */\r\n getDistanceMatrix() {\r\n let length = this.vertices.length;\r\n let adja = this.getAdjacencyMatrix();\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The distance matrix of the subgraph.\r\n */\r\n getSubgraphDistanceMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adja = this.getSubgraphAdjacencyMatrix(vertexIds);\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of the graph.\r\n *\r\n * @returns {Array[]} The adjancency list of the graph.\r\n */\r\n getAdjacencyList() {\r\n let length = this.vertices.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = [];\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(this.vertices[i].id, this.vertices[j].id)) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency list of the subgraph.\r\n */\r\n getSubgraphAdjacencyList(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = Array();\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Returns an array containing the edge ids of bridges. A bridge splits the graph into multiple components when removed.\r\n *\r\n * @returns {Number[]} An array containing the edge ids of the bridges.\r\n */\r\n getBridges() {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n let disc = new Array(length);\r\n let low = new Array(length);\r\n let parent = new Array(length);\r\n let adj = this.getAdjacencyList();\r\n let outBridges = Array();\r\n\r\n visited.fill(false);\r\n parent.fill(null);\r\n this._time = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (!visited[i]) {\r\n this._bridgeDfs(i, visited, disc, low, parent, adj, outBridges);\r\n }\r\n }\r\n\r\n return outBridges;\r\n }\r\n\r\n /**\r\n * Traverses the graph in breadth-first order.\r\n *\r\n * @param {Number} startVertexId The id of the starting vertex.\r\n * @param {Function} callback The callback function to be called on every vertex.\r\n */\r\n traverseBF(startVertexId, callback) {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n\r\n visited.fill(false);\r\n\r\n var queue = [startVertexId];\r\n\r\n while (queue.length > 0) {\r\n // JavaScripts shift() is O(n) ... bad JavaScript, bad!\r\n let u = queue.shift();\r\n let vertex = this.vertices[u];\r\n\r\n callback(vertex);\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n let v = vertex.neighbours[i];\r\n if (!visited[v]) {\r\n visited[v] = true;\r\n queue.push(v);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the depth of a subtree in the direction opposite to the vertex specified as the parent vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId The id of a neighbouring vertex.\r\n * @returns {Number} The depth of the sub-tree.\r\n */\r\n getTreeDepth(vertexId, parentVertexId) {\r\n if (vertexId === null || parentVertexId === null) {\r\n return 0;\r\n }\r\n\r\n let neighbours = this.vertices[vertexId].getSpanningTreeNeighbours(parentVertexId);\r\n let max = 0;\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n let childId = neighbours[i];\r\n let d = this.getTreeDepth(childId, vertexId);\r\n\r\n if (d > max) {\r\n max = d;\r\n }\r\n }\r\n\r\n return max + 1;\r\n }\r\n\r\n /**\r\n * Traverse a sub-tree in the graph.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId A neighbouring vertex.\r\n * @param {Function} callback The callback function that is called with each visited as an argument.\r\n * @param {Number} [maxDepth=999999] The maximum depth of the recursion.\r\n * @param {Boolean} [ignoreFirst=false] Whether or not to ignore the starting vertex supplied as vertexId in the callback.\r\n * @param {Number} [depth=1] The current depth in the tree.\r\n * @param {Uint8Array} [visited=null] An array holding a flag on whether or not a node has been visited.\r\n */\r\n traverseTree(vertexId, parentVertexId, callback, maxDepth = 999999, ignoreFirst = false, depth = 1, visited = null) {\r\n if (visited === null) {\r\n visited = new Uint8Array(this.vertices.length);\r\n }\r\n\r\n if (depth > maxDepth + 1 || visited[vertexId] === 1) {\r\n return;\r\n }\r\n\r\n visited[vertexId] = 1;\r\n\r\n let vertex = this.vertices[vertexId];\r\n let neighbours = vertex.getNeighbours(parentVertexId);\r\n\r\n if (!ignoreFirst || depth > 1) {\r\n callback(vertex);\r\n }\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n this.traverseTree(neighbours[i], vertexId, callback, maxDepth, ignoreFirst, depth + 1, visited);\r\n }\r\n }\r\n\r\n /**\r\n * Positiones the (sub)graph using Kamada and Kawais algorithm for drawing general undirected graphs. https://pdfs.semanticscholar.org/b8d3/bca50ccc573c5cb99f7d201e8acce6618f04.pdf\r\n * There are undocumented layout parameters. They are undocumented for a reason, so be very careful.\r\n *\r\n * @param {Number[]} vertexIds An array containing vertexIds to be placed using the force based layout.\r\n * @param {Vector2} center The center of the layout.\r\n * @param {Number} startVertexId A vertex id. Should be the starting vertex - e.g. the first to be positioned and connected to a previously place vertex.\r\n * @param {Ring} ring The bridged ring associated with this force-based layout.\r\n */\r\n kkLayout(vertexIds, center, startVertexId, ring, bondLength,\r\n threshold = 0.1, innerThreshold = 0.1, maxIteration = 2000,\r\n maxInnerIteration = 50, maxEnergy = 1e9) {\r\n\r\n let edgeStrength = bondLength;\r\n\r\n // Add vertices that are directly connected to the ring\r\n var i = vertexIds.length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n var j = vertex.neighbours.length;\r\n }\r\n\r\n let matDist = this.getSubgraphDistanceMatrix(vertexIds);\r\n let length = vertexIds.length;\r\n\r\n // Initialize the positions. Place all vertices on a ring around the center\r\n let radius = MathHelper.polyCircumradius(500, length);\r\n let angle = MathHelper.centralAngle(length);\r\n let a = 0.0;\r\n let arrPositionX = new Float32Array(length);\r\n let arrPositionY = new Float32Array(length);\r\n let arrPositioned = Array(length);\r\n\r\n i = length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n if (!vertex.positioned) {\r\n arrPositionX[i] = center.x + Math.cos(a) * radius;\r\n arrPositionY[i] = center.y + Math.sin(a) * radius;\r\n } else {\r\n arrPositionX[i] = vertex.position.x;\r\n arrPositionY[i] = vertex.position.y;\r\n }\r\n arrPositioned[i] = vertex.positioned;\r\n a += angle;\r\n }\r\n\r\n // Create the matrix containing the lengths\r\n let matLength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matLength[i] = new Array(length);\r\n var j = length;\r\n while (j--) {\r\n matLength[i][j] = bondLength * matDist[i][j];\r\n }\r\n }\r\n\r\n // Create the matrix containing the spring strenghts\r\n let matStrength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matStrength[i] = Array(length);\r\n var j = length;\r\n while (j--) {\r\n matStrength[i][j] = edgeStrength * Math.pow(matDist[i][j], -2.0);\r\n }\r\n }\r\n\r\n // Create the matrix containing the energies\r\n let matEnergy = Array(length);\r\n let arrEnergySumX = new Float32Array(length);\r\n let arrEnergySumY = new Float32Array(length);\r\n i = length;\r\n while (i--) {\r\n matEnergy[i] = Array(length);\r\n }\r\n\r\n i = length;\r\n let ux, uy, dEx, dEy, vx, vy, denom;\r\n\r\n while (i--) {\r\n ux = arrPositionX[i];\r\n uy = arrPositionY[i];\r\n dEx = 0.0;\r\n dEy = 0.0;\r\n let j = length;\r\n while (j--) {\r\n if (i === j) {\r\n continue;\r\n }\r\n vx = arrPositionX[j];\r\n vy = arrPositionY[j];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n matEnergy[i][j] = [\r\n matStrength[i][j] * ((ux - vx) - matLength[i][j] * (ux - vx) * denom),\r\n matStrength[i][j] * ((uy - vy) - matLength[i][j] * (uy - vy) * denom)\r\n ];\r\n matEnergy[j][i] = matEnergy[i][j];\r\n dEx += matEnergy[i][j][0];\r\n dEy += matEnergy[i][j][1];\r\n }\r\n arrEnergySumX[i] = dEx;\r\n arrEnergySumY[i] = dEy;\r\n }\r\n\r\n // Utility functions, maybe inline them later\r\n let energy = function (index) {\r\n return [arrEnergySumX[index] * arrEnergySumX[index] + arrEnergySumY[index] * arrEnergySumY[index], arrEnergySumX[index], arrEnergySumY[index]];\r\n };\r\n\r\n let highestEnergy = function () {\r\n let maxEnergy = 0.0;\r\n let maxEnergyId = 0;\r\n let maxDEX = 0.0;\r\n let maxDEY = 0.0;\r\n\r\n i = length;\r\n while (i--) {\r\n let [delta, dEX, dEY] = energy(i);\r\n\r\n if (delta > maxEnergy && arrPositioned[i] === false) {\r\n maxEnergy = delta;\r\n maxEnergyId = i;\r\n maxDEX = dEX;\r\n maxDEY = dEY;\r\n }\r\n }\r\n\r\n return [maxEnergyId, maxEnergy, maxDEX, maxDEY];\r\n };\r\n\r\n let update = function (index, dEX, dEY) {\r\n let dxx = 0.0;\r\n let dyy = 0.0;\r\n let dxy = 0.0;\r\n let ux = arrPositionX[index];\r\n let uy = arrPositionY[index];\r\n let arrL = matLength[index];\r\n let arrK = matStrength[index];\r\n\r\n i = length;\r\n while (i--) {\r\n if (i === index) {\r\n continue;\r\n }\r\n\r\n let vx = arrPositionX[i];\r\n let vy = arrPositionY[i];\r\n let l = arrL[i];\r\n let k = arrK[i];\r\n let m = (ux - vx) * (ux - vx);\r\n let denom = 1.0 / Math.pow(m + (uy - vy) * (uy - vy), 1.5);\r\n\r\n dxx += k * (1 - l * (uy - vy) * (uy - vy) * denom);\r\n dyy += k * (1 - l * m * denom);\r\n dxy += k * (l * (ux - vx) * (uy - vy) * denom);\r\n }\r\n\r\n // Prevent division by zero\r\n if (dxx === 0) {\r\n dxx = 0.1;\r\n }\r\n\r\n if (dyy === 0) {\r\n dyy = 0.1;\r\n }\r\n\r\n if (dxy === 0) {\r\n dxy = 0.1;\r\n }\r\n\r\n let dy = (dEX / dxx + dEY / dxy);\r\n dy /= (dxy / dxx - dyy / dxy); // had to split this onto two lines because the syntax highlighter went crazy.\r\n let dx = -(dxy * dy + dEX) / dxx;\r\n\r\n arrPositionX[index] += dx;\r\n arrPositionY[index] += dy;\r\n\r\n // Update the energies\r\n let arrE = matEnergy[index];\r\n dEX = 0.0;\r\n dEY = 0.0;\r\n\r\n ux = arrPositionX[index];\r\n uy = arrPositionY[index];\r\n\r\n let vx, vy, prevEx, prevEy, denom;\r\n\r\n i = length;\r\n while (i--) {\r\n if (index === i) {\r\n continue;\r\n }\r\n vx = arrPositionX[i];\r\n vy = arrPositionY[i];\r\n // Store old energies\r\n prevEx = arrE[i][0];\r\n prevEy = arrE[i][1];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n dx = arrK[i] * ((ux - vx) - arrL[i] * (ux - vx) * denom);\r\n dy = arrK[i] * ((uy - vy) - arrL[i] * (uy - vy) * denom);\r\n\r\n arrE[i] = [dx, dy];\r\n dEX += dx;\r\n dEY += dy;\r\n arrEnergySumX[i] += dx - prevEx;\r\n arrEnergySumY[i] += dy - prevEy;\r\n }\r\n arrEnergySumX[index] = dEX;\r\n arrEnergySumY[index] = dEY;\r\n };\r\n\r\n // Setting up variables for the while loops\r\n let maxEnergyId = 0;\r\n let dEX = 0.0;\r\n let dEY = 0.0;\r\n let delta = 0.0;\r\n let iteration = 0;\r\n let innerIteration = 0;\r\n\r\n while (maxEnergy > threshold && maxIteration > iteration) {\r\n iteration++;\r\n [maxEnergyId, maxEnergy, dEX, dEY] = highestEnergy();\r\n delta = maxEnergy;\r\n innerIteration = 0;\r\n while (delta > innerThreshold && maxInnerIteration > innerIteration) {\r\n innerIteration++;\r\n update(maxEnergyId, dEX, dEY);\r\n [delta, dEX, dEY] = energy(maxEnergyId);\r\n }\r\n }\r\n\r\n i = length;\r\n while (i--) {\r\n let index = vertexIds[i];\r\n let vertex = this.vertices[index];\r\n vertex.position.x = arrPositionX[i];\r\n vertex.position.y = arrPositionY[i];\r\n vertex.positioned = true;\r\n vertex.forcePositioned = true;\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getBridges().\r\n */\r\n _bridgeDfs(u, visited, disc, low, parent, adj, outBridges) {\r\n visited[u] = true;\r\n disc[u] = low[u] = ++this._time;\r\n\r\n for (var i = 0; i < adj[u].length; i++) {\r\n let v = adj[u][i];\r\n\r\n if (!visited[v]) {\r\n parent[v] = u;\r\n\r\n this._bridgeDfs(v, visited, disc, low, parent, adj, outBridges);\r\n\r\n low[u] = Math.min(low[u], low[v]);\r\n\r\n // If low > disc, we have a bridge\r\n if (low[v] > disc[u]) {\r\n outBridges.push([u, v]);\r\n }\r\n } else if (v !== parent[u]) {\r\n low[u] = Math.min(low[u], disc[v]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the connected components of the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Set[]} Connected components as sets.\r\n */\r\n static getConnectedComponents(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let components = [];\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n let component = Array();\r\n visited[u] = true;\r\n component.push(u);\r\n count++;\r\n Graph._ccGetDfs(u, visited, adjacencyMatrix, component);\r\n if (component.length > 1) {\r\n components.push(component);\r\n }\r\n }\r\n }\r\n\r\n return components;\r\n }\r\n\r\n /**\r\n * Returns the number of connected components for the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of connected components of the supplied graph.\r\n */\r\n static getConnectedComponentCount(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n visited[u] = true;\r\n count++;\r\n Graph._ccCountDfs(u, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponentCount().\r\n */\r\n static _ccCountDfs(u, visited, adjacencyMatrix) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n Graph._ccCountDfs(v, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponents().\r\n */\r\n static _ccGetDfs(u, visited, adjacencyMatrix, component) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n component.push(v);\r\n Graph._ccGetDfs(v, visited, adjacencyMatrix, component);\r\n }\r\n }\r\n\r\n /**\r\n * Revert decay point value and update list of decay points\r\n * when edge isn't decay point -> change mark edge as decay point and add edge to decays list\r\n * when edge is decay point -> unmark edge as decay point and remove edgeId from list of decays\r\n * @param edgeId\r\n */\r\n revertEdgeDecayPoint(edgeId) {\r\n this.edges[edgeId].isDecay = !this.edges[edgeId].isDecay;\r\n this.edges[edgeId].isDecayAll = !this.edges[edgeId].isDecayAll;\r\n if (this.edges[edgeId].isDecay) {\r\n this.decays.push(edgeId);\r\n this.decaysAll.push(edgeId);\r\n } else {\r\n let index = this.decays.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decays.splice(index, 1);\r\n }\r\n index = this.decaysAll.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decaysAll.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.decays;\r\n }\r\n\r\n /**\r\n * Build block of SMILES based on decay points\r\n * DFS pass through graph\r\n * but the numbers are already setup in vertex.value.ringbonds array so no need to second pass of dfs\r\n */\r\n buildSmiles() {\r\n let smiles = [];\r\n this._polyketide = false;\r\n this.dfsSmilesInitialization();\r\n if (this.decays.length === 0) {\r\n this.startDfs(this.vertices[0], smiles);\r\n return {blockSmiles: smiles, sequence: '[0]', sequenceType: SequenceType.VALUES.OTHER, decays: this.decays, isPolyketide: this._polyketide};\r\n } else {\r\n this.dfsBuildSmilesStart(smiles);\r\n }\r\n this.dfsSmilesInitialization();\r\n this.dfsSmallStart();\r\n this._smallGraph.oneCyclic();\r\n this._smallGraph.dfsSequenceStart();\r\n\r\n let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence);\r\n\r\n return {\r\n blockSmiles: sequenceData.smiles,\r\n sequence: sequenceData.sequence,\r\n sequenceType: this._smallGraph.sequenceType + ((this._smallGraph.sequenceType === 'linear' || this._smallGraph.sequenceType === 'cyclic') && this._polyketide ? '-polyketide' : ''),\r\n decays: this.decays,\r\n isPolyketide: this._polyketide\r\n }\r\n }\r\n\r\n sortSequence(smiles, sequence) {\r\n let permutation = this.getSequencePermutation(sequence);\r\n let newSmiles = new Array(permutation.length).fill(null);\r\n for (let i = 0; i < permutation.length; ++i) {\r\n newSmiles[i] = smiles[permutation[i][0]];\r\n }\r\n\r\n let position = 0;\r\n let char = sequence.charAt(position);\r\n let newSequence = '';\r\n while (true) {\r\n switch (char) {\r\n case '0':\r\n case '1':\r\n case '2':\r\n case '3':\r\n case '4':\r\n case '5':\r\n case '6':\r\n case '7':\r\n case '8':\r\n case '9':\r\n let number = char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n while(!isNaN(char)) {\r\n number += char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n let j;\r\n for (j = 0; j < permutation.length; ++j) {\r\n if (permutation[j][0] === number) {\r\n newSequence += j;\r\n break;\r\n }\r\n }\r\n continue;\r\n default:\r\n newSequence += char;\r\n }\r\n\r\n ++position;\r\n if (position >= sequence.length) {\r\n break;\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n return {sequence: newSequence, smiles: newSmiles};\r\n }\r\n\r\n getSequencePermutation(sequence) {\r\n let re = /\\d+/g;\r\n let match = null;\r\n let permutation = [];\r\n while ((match = re.exec(sequence)) != null) {\r\n permutation.push(match);\r\n }\r\n return permutation;\r\n }\r\n\r\n dfsSmallStart() {\r\n this._smallGraph = new SmallGraph();\r\n for (let index = 0; index < this._startingVertexes.length; ++index) {\r\n this._smallGraph.addVertex(new Node(this._startingVertexes[index].component));\r\n this.first = this._startingVertexes[index];\r\n this.dfsSmall(this._startingVertexes[index], this._componentsIsPolyketide[index]);\r\n }\r\n }\r\n\r\n /**\r\n * Initialize graph for dfs\r\n * set for all vertices vertexState to NotFound\r\n */\r\n dfsSmilesInitialization() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n /**\r\n * Starting function for DFS\r\n * starts on decay points (on edge), so start on both side of edge\r\n * @param {Array} smiles output param, array of SMILES blocks (string)\r\n */\r\n dfsBuildSmilesStart(smiles) {\r\n this._cnt = 0;\r\n this._markComponent = false;\r\n this._startingVertexes = [];\r\n for (let i = 0; i < this.decays.length; ++i) {\r\n let edge = this.edges[this.decays[i]];\r\n this.markingComponents(this.startDfs(this.vertices[edge.sourceId], smiles));\r\n this.markingComponents(this.startDfs(this.vertices[edge.targetId], smiles));\r\n }\r\n }\r\n\r\n markingComponents(isPolyketyde) {\r\n if (this._markComponent) {\r\n this._cnt++;\r\n this._markComponent = false;\r\n this._componentsIsPolyketide.push(isPolyketyde);\r\n }\r\n }\r\n\r\n /**\r\n * Start DFS for build SMILES of blocks\r\n * @param {Vertex} vertex to start DFS\r\n * @param {Array} smiles output param, array od SMILES\r\n */\r\n startDfs(vertex, smiles) {\r\n let isPolyketide = new MutableBoolean(true);\r\n let decaysCounter = new MutableCounter();\r\n let vertexCounter = new MutableCounter();\r\n let through = [];\r\n let stackSmiles = [];\r\n this.first = vertex.id;\r\n this._isCyclic = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.dfsSmiles(vertex, stackSmiles, isPolyketide, decaysCounter, through, vertexCounter);\r\n if (decaysCounter.getValue() < 2 && isPolyketide.getValue() === true) {\r\n isPolyketide.setValue(through.every(vertex => vertex === 'O' || vertex === 'N') && vertexCounter.getValue() > 4);\r\n }\r\n if (this._isCyclic) {\r\n this.closedToNotFound();\r\n stackSmiles = [];\r\n this.dfsSmiles(vertex, stackSmiles, new MutableBoolean(true), new MutableCounter(), [], new MutableCounter(), -1, true);\r\n }\r\n this.closedToFullyClosed();\r\n\r\n stackSmiles = Graph.removeUnnecessaryParentheses(stackSmiles);\r\n let smile = Graph.removeUnnecessaryNumbers(stackSmiles.join(\"\"));\r\n if (smile.length !== 0) {\r\n smiles.push({smiles: smile, isPolyketide: isPolyketide.getValue()});\r\n if (isPolyketide.getValue() === true) {\r\n this._polyketide = true;\r\n }\r\n }\r\n return isPolyketide.getValue();\r\n }\r\n\r\n closedToNotFound() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n }\r\n\r\n closedToFullyClosed() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.FULLY_CLOSED;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * DFS for SMILES\r\n * @param {Vertex} vertex\r\n * @param {Array} stackSmiles output param\r\n * @param {MutableBoolean} isPolyketide\r\n * @param {MutableCounter} cntDecays\r\n * @param {Array} through\r\n * @param {MutableCounter} vertexCounter\r\n * @param lastVertexId last vertex id for setup digits\r\n * @param isSecondPass is second pass of dfs\r\n */\r\n dfsSmiles(vertex, stackSmiles, isPolyketide, cntDecays, through, vertexCounter, lastVertexId = -1, isSecondPass = false) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN && !isSecondPass && lastVertexId !== -1) {\r\n this._isCyclic = true;\r\n if (!vertex.digits.some(e => this.vertices[lastVertexId].digits.includes(e))) {\r\n vertex.digits.push(this._digitCounter);\r\n this.vertices[lastVertexId].digits.push(this._digitCounter);\r\n this._digitCounter++;\r\n }\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n if (vertex.value.element === 'H') {\r\n return;\r\n }\r\n\r\n if (this.first === vertex.id && vertex.value.element === \"C\" && isPolyketide.getValue()) {\r\n stackSmiles.push(\"O\");\r\n isPolyketide.setValue(false);\r\n }\r\n\r\n if (vertex.value.bracket) {\r\n stackSmiles.push(\"[\");\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n if (vertex.value.bracket.hcount > 0) {\r\n stackSmiles.push('H');\r\n if (vertex.value.bracket.hcount > 1) {\r\n stackSmiles.push(vertex.value.bracket.hcount);\r\n }\r\n }\r\n if (vertex.value.bracket.charge > 0) {\r\n stackSmiles.push('+');\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n } else if (vertex.value.bracket.charge < 0) {\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n }\r\n stackSmiles.push(\"]\");\r\n } else {\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n }\r\n vertexCounter.increment();\r\n\r\n if (isSecondPass) {\r\n stackSmiles.push(this.smilesNumbersAdd(vertex));\r\n }\r\n\r\n if (!this._markComponent) {\r\n this._startingVertexes.push(vertex);\r\n }\r\n vertex.component = this._cnt;\r\n this._markComponent = true;\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n if (edge.isDecayAll && lastVertexId !== nextVertex) {\r\n through.push(vertex.value.element);\r\n }\r\n if (edge.isDecay) {\r\n cntDecays.increment();\r\n if (vertex.value.element === \"C\" && vertex.id !== this.first && isPolyketide.getValue()) {\r\n stackSmiles.push(\"(\");\r\n stackSmiles.push(\"O\");\r\n stackSmiles.push(\")\");\r\n isPolyketide.setValue(false);\r\n }\r\n continue;\r\n }\r\n stackSmiles.push(\"(\");\r\n Graph.addBondTypeToStack(edge, stackSmiles);\r\n if (lastVertexId !== nextVertex) {\r\n this.dfsSmiles(this.vertices[nextVertex], stackSmiles, isPolyketide, cntDecays, through, vertexCounter, vertex.id, isSecondPass);\r\n }\r\n Graph.checkStack(stackSmiles);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSmall(vertex, isPolyketide) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n\r\n this._smallGraph.addNeighbour(vertex.component, this.vertices[Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId)].component, Direction.getProperValue(isPolyketide, vertex.value.element, vertex.id, this.first));\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n this.dfsSmall(this.vertices[nextVertex], isPolyketide);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n\r\n static printVertexValue(stackSmiles, vertex) {\r\n if (vertex.value.isPartOfAromaticRing) {\r\n stackSmiles.push(vertex.value.element.toLowerCase());\r\n } else {\r\n stackSmiles.push(vertex.value.element);\r\n }\r\n }\r\n\r\n /**\r\n * Remove numbers which is neighbours in SMILES notation -> need to perform in cyclic structures\r\n * @param {String} smiles SMILES\r\n * @return {String} repaired SMILES\r\n */\r\n static removeUnnecessaryNumbers(smiles) {\r\n if (smiles === null) {\r\n return '';\r\n }\r\n try {\r\n let numbers = this.getNumbers(smiles);\r\n for (let number of numbers) {\r\n let first = this.findFirst(smiles, number);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n let tmpRange = this.removeRangeLast(smiles, first, second, number);\r\n smiles = this.repairSmiles(smiles, tmpRange, first, second, number);\r\n }\r\n return smiles;\r\n } catch (ex) {\r\n return smiles;\r\n }\r\n }\r\n\r\n /**\r\n * Remove unnecessary numbers from SMILES\r\n * @param {String} smiles\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {*}\r\n */\r\n static removeNumbers(smiles, first, second, number) {\r\n if (number > 9) {\r\n let numLength = number.toString().length;\r\n smiles = smiles.slice(0, first - 1) + smiles.slice(first + numLength);\r\n return smiles.slice(0, second - 2 - numLength) + smiles.slice(second - 1);\r\n } else {\r\n smiles = smiles.slice(0, first) + smiles.slice(first + 1);\r\n return smiles.slice(0, second - 1) + smiles.slice(second);\r\n }\r\n }\r\n\r\n /**\r\n * Reapair SMILES\r\n * @param {String} smiles\r\n * @param {String} tmpRange\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {String|*}\r\n */\r\n static repairSmiles(smiles, tmpRange, first, second, number) {\r\n let pattern = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])$\");\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let patternOrg = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])\");\r\n if (patternOrg.test(tmpRange)) {\r\n return smiles;\r\n }\r\n\r\n while (tmpRange.length !== 0) {\r\n if (tmpRange[0] === '(') {\r\n tmpRange = tmpRange.substring(1);\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let leftBrackets = 1;\r\n let rightBrackets = 0;\r\n while (leftBrackets !== rightBrackets) {\r\n switch (tmpRange[0]) {\r\n case '(':\r\n leftBrackets++;\r\n break;\r\n case ')':\r\n rightBrackets++;\r\n break;\r\n }\r\n if (\"\" === tmpRange) {\r\n return smiles;\r\n }\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n return this.repairSmiles(smiles, tmpRange, first, second, number);\r\n } else {\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Substring in range and remove last Organic Subset\r\n * @param smiles\r\n * @param first\r\n * @param second\r\n * @param number\r\n * @return {string}\r\n */\r\n static removeRangeLast(smiles, first, second, number) {\r\n if (number > 9) {\r\n return smiles.substring(first + number.toString().length, second - 1);\r\n } else {\r\n return smiles.substring(first + 1, second);\r\n }\r\n }\r\n\r\n /**\r\n * Get numbers from SMILES\r\n * @param smiles\r\n * @return {Set}\r\n */\r\n static getNumbers(smiles) {\r\n let numbers = new Set();\r\n for (let index = 0; index < smiles.length; ++index) {\r\n if (!isNaN(smiles[index])) {\r\n numbers.add(smiles[index]);\r\n } else if (smiles[index] === '%') {\r\n index++;\r\n let num = \"\";\r\n while (!isNaN(smiles[index])) {\r\n num += smiles[index];\r\n index++;\r\n if (index >= smiles.length) {\r\n break;\r\n }\r\n }\r\n index--;\r\n numbers.add(num);\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * return index of first occurrence number\r\n * @param smiles\r\n * @param number\r\n * @return {number}\r\n */\r\n static findFirst(smiles, number) {\r\n return smiles.indexOf(number);\r\n }\r\n\r\n /**\r\n * return index of first occurrence number from index + 1\r\n * @param smiles\r\n * @param from range no including this point (from, Infinity) = [from + 1, Infinity)\r\n * @param number\r\n * @return {*}\r\n */\r\n static findSecond(smiles, from, number) {\r\n let result = smiles.indexOf(number, from);\r\n if (result === -1) {\r\n throw \"Not Found\";\r\n }\r\n return result;\r\n }\r\n\r\n\r\n smilesNumbersAdd(vertex) {\r\n let numbers = '';\r\n for (let i = 0; i < vertex.digits.length; ++i) {\r\n let num = vertex.digits[i];\r\n if (this._printedDigits.some(e => e === num)) {\r\n let nextVertex = this.vertices.find(e => e.digits.includes(num) && e.id !== vertex.id);\r\n let intersection = vertex.edges.filter(element => nextVertex.edges.includes(element));\r\n\r\n if (intersection.length > 0) {\r\n let bond = this.edges[intersection[0]].bondType;\r\n if (bond !== '-') {\r\n numbers += bond;\r\n }\r\n }\r\n }\r\n\r\n this._printedDigits.push(num);\r\n let numString = num.toString();\r\n if (numString.length === 1) {\r\n numbers += numString;\r\n } else {\r\n numbers += '%' + numString;\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * Return other vertex id then the actual vertex id\r\n * when vertexId === sourceId return targetId\r\n * when vertexId === targetId return sourceId\r\n * @param {Number} vertexId actual vertex id\r\n * @param {Number} sourceId source vertex id\r\n * @param {Number} targetId target vertex id\r\n * @return {Number}\r\n */\r\n static getProperVertex(vertexId, sourceId, targetId) {\r\n if (vertexId === sourceId) return targetId;\r\n else return sourceId;\r\n }\r\n\r\n static repairNumbers(smiles) {\r\n try {\r\n let numbers = Array.from(this.getNumbers(smiles));\r\n numbers.sort(function (a, b) {\r\n return b - a\r\n });\r\n\r\n let index = 1;\r\n for (let number of numbers) {\r\n if (index === number) {\r\n continue;\r\n }\r\n let first = this.findFirst(smiles, number);\r\n if (number > 9) {\r\n smiles = smiles.slice(0, first - 1) + index + smiles.slice(first + number.toString().length);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second - 1) + index + smiles.slice(second + number.toString().length);\r\n } else {\r\n smiles = smiles.slice(0, first) + index + smiles.slice(first + 1);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second) + index + smiles.slice(second + 1);\r\n }\r\n index++;\r\n }\r\n } catch (e) {\r\n return smiles;\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from SMILES\r\n * example CCC(CC)(C) -> CCC(CC)C\r\n * example C(=O)C(C(C)) -> C(=O)CCC\r\n * @param {Array} stackRight\r\n * @return {Array}\r\n */\r\n static removeUnnecessaryParentheses(stackRight) {\r\n if (stackRight.length === 0) return [];\r\n let stackLeft = [], lastLiteral = \"\", literal = \"\";\r\n while (stackRight.length > 0) {\r\n literal = stackRight.shift();\r\n if ((\")\".localeCompare(literal) === 0 && \")\".localeCompare(lastLiteral) === 0)) {\r\n Graph.removeParentheses(stackLeft, false, literal);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n lastLiteral = literal;\r\n }\r\n\r\n literal = stackLeft.pop();\r\n if ((\")\".localeCompare(literal) === 0 && stackRight.length === 0)) {\r\n Graph.removeParentheses(stackLeft);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n return stackLeft;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from stack\r\n * go through stack and when find proper closing bracket,\r\n * then remove it and push back removed data when searching in stack\r\n * @param {Array} stack with unnecessary parentheses to remove\r\n * @param {Boolean} end treat with situation when \")\" is last character of stack -> end = true, else where end = false\r\n * @param {String} literal, when end = false, need to pop from stack and at the end add literal back to stack\r\n */\r\n static removeParentheses(stack, end = true, literal = \"\") {\r\n let stackTmp = [];\r\n let leftBraces = 0, rightBraces = 1;\r\n if (!end) {\r\n stack.pop();\r\n }\r\n while (true) {\r\n let lit = stack.pop();\r\n if (\"(\".localeCompare(lit) === 0) {\r\n leftBraces++;\r\n } else if (\")\".localeCompare(lit) === 0) {\r\n rightBraces++;\r\n }\r\n if (leftBraces === rightBraces) {\r\n Graph.moveAllValuesInStackToAnotherStack(stackTmp, stack);\r\n if (!end) {\r\n stack.push(literal);\r\n }\r\n break;\r\n }\r\n stackTmp.push(lit);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all values from stackSource and push it to stackDestination\r\n * @param {Array} stackSource stack to remove values\r\n * @param {Array} stackDestination stack to add values from stackSource\r\n */\r\n static moveAllValuesInStackToAnotherStack(stackSource, stackDestination) {\r\n while (stackSource.length > 0) {\r\n stackDestination.push(stackSource.pop());\r\n }\r\n }\r\n\r\n /**\r\n * Check last value of stack\r\n * if it one of (, -, = or # then remove all characters in stack to first ( from the end of stack\r\n * elsewhere add ) to stack\r\n * @param {Array} stackSmiles\r\n */\r\n static checkStack(stackSmiles) {\r\n switch (stackSmiles[stackSmiles.length - 1]) {\r\n case \"(\":\r\n case \"-\":\r\n case \"=\":\r\n case \"#\":\r\n Graph.removeAllFromStackToFirstLeftBrace(stackSmiles);\r\n break;\r\n default:\r\n stackSmiles.push(\")\");\r\n }\r\n }\r\n\r\n /**\r\n * Remove all characters from stack to first \"(\"\r\n * @param {Array} stackSmiles\r\n */\r\n static removeAllFromStackToFirstLeftBrace(stackSmiles) {\r\n let literal = stackSmiles.pop();\r\n while (literal !== \"(\") {\r\n if (stackSmiles.length === 0) break;\r\n literal = stackSmiles.pop();\r\n }\r\n }\r\n\r\n /**\r\n * Add bond type to stack\r\n * if edge have = or # bond type add it to stack\r\n * @param {Edge} edge\r\n * @param {Array} stackSmiles\r\n */\r\n static addBondTypeToStack(edge, stackSmiles) {\r\n if (edge.bondType === \"=\" || edge.bondType === \"#\") {\r\n stackSmiles.push(edge.bondType);\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Graph;\r\n","//@ts-check\r\nconst Vector2 = require('./Vector2')\r\n\r\n/** \r\n * A class representing a line.\r\n * \r\n * @property {Vector2} from The Vector2 defining the start of the line.\r\n * @property {Vector2} to The Vector2 defining the end of the line.\r\n * @property {String} elementFrom The element symbol associated with the start of the line.\r\n * @property {String} elementTo The element symbol associated with the end of the line.\r\n * @property {Boolean} chiralFrom A boolean indicating whether or not the source atom is a chiral center.\r\n * @property {Boolean} chiralTo A boolean indicating whether or tno the target atom is a chiral center.\r\n */\r\nclass Line {\r\n /**\r\n * The constructor for the class Line.\r\n *\r\n * @param {Vector2} [from=new Vector2(0, 0)] A vector marking the beginning of the line.\r\n * @param {Vector2} [to=new Vector2(0, 0)] A vector marking the end of the line.\r\n * @param {string} [elementFrom=null] A one-letter representation of the element associated with the vector marking the beginning of the line.\r\n * @param {string} [elementTo=null] A one-letter representation of the element associated with the vector marking the end of the line.\r\n * @param {Boolean} [chiralFrom=false] Whether or not the from atom is a chiral center.\r\n * @param {Boolean} [chiralTo=false] Whether or not the to atom is a chiral center.\r\n * @param {Boolean} [isDecayPoint=false] Whether or not the edge is a decay point\r\n */\r\n constructor(from = new Vector2(0,0), to = new Vector2(0, 0), elementFrom = null, elementTo = null, chiralFrom = false, chiralTo = false, isDecayPoint = false) {\r\n this.from = from;\r\n this.to = to;\r\n this.elementFrom = elementFrom;\r\n this.elementTo = elementTo;\r\n this.chiralFrom = chiralFrom;\r\n this.chiralTo = chiralTo;\r\n this.isDecayPoint = isDecayPoint;\r\n }\r\n\r\n /**\r\n * Clones this line and returns the clone.\r\n *\r\n * @returns {Line} A clone of this line.\r\n */\r\n clone() {\r\n return new Line(this.from.clone(), this.to.clone(), this.elementFrom, this.elementTo);\r\n }\r\n\r\n /**\r\n * Returns the length of this line.\r\n *\r\n * @returns {Number} The length of this line.\r\n */\r\n getLength() {\r\n return Math.sqrt(Math.pow(this.to.x - this.from.x, 2) + \r\n Math.pow(this.to.y - this.from.y, 2));\r\n }\r\n\r\n\r\n /**\r\n * Returns the angle of the line in relation to the coordinate system (the x-axis).\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n // Get the angle between the line and the x-axis\r\n let diff = Vector2.subtract(this.getRightVector(), this.getLeftVector());\r\n return diff.angle();\r\n }\r\n\r\n /**\r\n * Returns the right vector (the vector with the larger x value).\r\n *\r\n * @returns {Vector2} The right vector.\r\n */\r\n getRightVector() {\r\n // Return the vector with the larger x value (the right one)\r\n if (this.from.x < this.to.x) {\r\n return this.to;\r\n } else {\r\n return this.from;\r\n }\r\n }\r\n \r\n /**\r\n * Returns the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {Vector2} The left vector.\r\n */\r\n getLeftVector() {\r\n // Return the vector with the smaller x value (the left one)\r\n if (this.from.x < this.to.x) {\r\n return this.from;\r\n } else {\r\n return this.to;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the right vector (the vector with the larger x value).\r\n *\r\n * @returns {String} The element associated with the right vector.\r\n */\r\n getRightElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementTo;\r\n } else {\r\n return this.elementFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {String} The element associated with the left vector.\r\n */\r\n getLeftElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementFrom;\r\n } else {\r\n return this.elementTo;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the right vector (the vector with the larger x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the right vector is a chiral center.\r\n */\r\n getRightChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralTo;\r\n } else {\r\n return this.chiralFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the left vector (the vector with the smaller x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the left vector is a chiral center.\r\n */\r\n getLeftChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralFrom;\r\n } else {\r\n return this.chiralTo;\r\n }\r\n }\r\n\r\n /**\r\n * Set the value of the right vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setRightVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.to.x = x;\r\n this.to.y = y;\r\n } else {\r\n this.from.x = x;\r\n this.from.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Set the value of the left vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setLeftVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.from.x = x;\r\n this.from.y = y;\r\n } else {\r\n this.to.x = x;\r\n this.to.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this line to be aligned with the x-axis. The center of rotation is the left vector.\r\n *\r\n * @returns {Line} This line.\r\n */\r\n rotateToXAxis() {\r\n let left = this.getLeftVector();\r\n \r\n this.setRightVector(left.x + this.getLength(), left.y);\r\n \r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate the line by a given value (in radians). The center of rotation is the left vector.\r\n *\r\n * @param {Number} theta The angle (in radians) to rotate the line.\r\n * @returns {Line} This line.\r\n */\r\n rotate(theta) {\r\n let l = this.getLeftVector();\r\n let r = this.getRightVector();\r\n let sinTheta = Math.sin(theta);\r\n let cosTheta = Math.cos(theta);\r\n\r\n let x = cosTheta * (r.x - l.x) - sinTheta * (r.y - l.y) + l.x;\r\n let y = sinTheta * (r.x - l.x) - cosTheta * (r.y - l.y) + l.y;\r\n \r\n this.setRightVector(x, y);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"from\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenFrom(by) {\r\n let f = Vector2.subtract(this.to, this.from);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.from.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"to\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenTo(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.to.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shorten the right side.\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenRight(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenTo(by);\r\n } else {\r\n this.shortenFrom(by);\r\n }\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Shorten the left side.\r\n * \r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenLeft(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenFrom(by);\r\n } else {\r\n this.shortenTo(by);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from both directions by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shorten(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by / 2.0);\r\n \r\n this.to.add(f);\r\n this.from.subtract(f);\r\n\r\n return this;\r\n }\r\n}\r\n\r\nmodule.exports = Line;","/** \r\n * A static class containing helper functions for math-related tasks. \r\n */\r\nclass MathHelper {\r\n /**\r\n * Rounds a value to a given number of decimals.\r\n *\r\n * @static\r\n * @param {Number} value A number.\r\n * @param {Number} decimals The number of decimals.\r\n * @returns {Number} A number rounded to a given number of decimals.\r\n */\r\n static round(value, decimals) {\r\n decimals = decimals ? decimals : 1;\r\n return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);\r\n }\r\n\r\n /**\r\n * Returns the means of the angles contained in an array. In radians.\r\n *\r\n * @static\r\n * @param {Number[]} arr An array containing angles (in radians).\r\n * @returns {Number} The mean angle in radians.\r\n */\r\n static meanAngle(arr) {\r\n let sin = 0.0;\r\n let cos = 0.0;\r\n \r\n for (var i = 0; i < arr.length; i++) {\r\n sin += Math.sin(arr[i]);\r\n cos += Math.cos(arr[i]);\r\n }\r\n\r\n return Math.atan2(sin / arr.length, cos / arr.length);\r\n }\r\n\r\n /**\r\n * Returns the inner angle of a n-sided regular polygon.\r\n *\r\n * @static\r\n * @param {Number} n Number of sides of a regular polygon.\r\n * @returns {Number} The inner angle of a given regular polygon.\r\n */\r\n static innerAngle(n) {\r\n return MathHelper.toRad((n - 2) * 180 / n);\r\n }\r\n\r\n /**\r\n * Returns the circumradius of a n-sided regular polygon with a given side-length.\r\n *\r\n * @static\r\n * @param {Number} s The side length of the regular polygon.\r\n * @param {Number} n The number of sides.\r\n * @returns {Number} The circumradius of the regular polygon.\r\n */\r\n static polyCircumradius(s, n) {\r\n return s / (2 * Math.sin(Math.PI / n));\r\n }\r\n\r\n /**\r\n * Returns the apothem of a regular n-sided polygon based on its radius.\r\n *\r\n * @static\r\n * @param {Number} r The radius.\r\n * @param {Number} n The number of edges of the regular polygon.\r\n * @returns {Number} The apothem of a n-sided polygon based on its radius.\r\n */\r\n static apothem(r, n) {\r\n return r * Math.cos(Math.PI / n);\r\n }\r\n\r\n static apothemFromSideLength(s, n) {\r\n let r = MathHelper.polyCircumradius(s, n);\r\n \r\n return MathHelper.apothem(r, n);\r\n }\r\n\r\n /**\r\n * The central angle of a n-sided regular polygon. In radians.\r\n *\r\n * @static\r\n * @param {Number} n The number of sides of the regular polygon.\r\n * @returns {Number} The central angle of the n-sided polygon in radians.\r\n */\r\n static centralAngle(n) {\r\n return MathHelper.toRad(360 / n);\r\n }\r\n\r\n /**\r\n * Convertes radians to degrees.\r\n *\r\n * @static\r\n * @param {Number} rad An angle in radians.\r\n * @returns {Number} The angle in degrees.\r\n */\r\n static toDeg(rad) {\r\n return rad * MathHelper.degFactor;\r\n }\r\n\r\n /**\r\n * Converts degrees to radians.\r\n *\r\n * @static\r\n * @param {Number} deg An angle in degrees.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static toRad(deg) {\r\n return deg * MathHelper.radFactor;\r\n }\r\n\r\n /**\r\n * Returns the parity of the permutation (1 or -1)\r\n * @param {(Array|Uint8Array)} arr An array containing the permutation.\r\n * @returns {Number} The parity of the permutation (1 or -1), where 1 means even and -1 means odd.\r\n */\r\n static parityOfPermutation(arr) {\r\n let visited = new Uint8Array(arr.length);\r\n let evenLengthCycleCount = 0;\r\n\r\n let traverseCycle = function(i, cycleLength = 0) {\r\n if (visited[i] === 1) {\r\n return cycleLength;\r\n }\r\n\r\n cycleLength++;\r\n\r\n visited[i] = 1;\r\n return traverseCycle(arr[i], cycleLength);\r\n }\r\n\r\n for (var i = 0; i < arr.length; i++) {\r\n if (visited[i] === 1) {\r\n continue;\r\n }\r\n\r\n let cycleLength = traverseCycle(i);\r\n evenLengthCycleCount += (1 - cycleLength % 2);\r\n }\r\n\r\n return evenLengthCycleCount % 2 ? -1 : 1;\r\n }\r\n\r\n /** The factor to convert degrees to radians. */\r\n static get radFactor() {\r\n return Math.PI / 180.0;\r\n }\r\n\r\n /** The factor to convert radians to degrees. */\r\n static get degFactor() {\r\n return 180.0 / Math.PI;\r\n }\r\n\r\n /** Two times PI. */\r\n static get twoPI() {\r\n return 2.0 * Math.PI;\r\n }\r\n}\r\n\r\nmodule.exports = MathHelper;","/**\r\n *@property {boolean} value is boolean\r\n */\r\nclass MutableBoolean {\r\n\r\n /**\r\n * @param {boolean} value\r\n */\r\n constructor(value) {\r\n this.value = value;\r\n }\r\n\r\n setValue(value) {\r\n this.value = value;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableBoolean;\r\n","/**\r\n * @param {Number} value\r\n */\r\nclass MutableCounter {\r\n\r\n constructor() {\r\n this.value = 0;\r\n }\r\n\r\n increment() {\r\n this.value++;\r\n }\r\n\r\n reset() {\r\n this.value = 0;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableCounter;\r\n","\r\nclass Neighbour {\r\n\r\n constructor(neighbour, direction) {\r\n this.neighbour = neighbour;\r\n this.direction = direction;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Neighbour;\r\n","//@ts-check\r\nconst VertexState = require(\"./VertexState\");\r\n\r\nclass Node {\r\n\r\n constructor(id) {\r\n this.id = id;\r\n this.neighbours = [];\r\n this.onRing = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n\r\n addNeighbour(neighbour) {\r\n this.neighbours.push(neighbour);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Node;\r\n","// WHEN REPLACING, CHECK FOR:\r\n// KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\nmodule.exports = (function () {\r\n \"use strict\";\r\n\r\n /*\r\n * Generated by PEG.js 0.10.0.\r\n *\r\n * http://pegjs.org/\r\n */\r\n\r\n function peg$subclass(child, parent) {\r\n function ctor() {\r\n this.constructor = child;\r\n }\r\n ctor.prototype = parent.prototype;\r\n child.prototype = new ctor();\r\n }\r\n\r\n function peg$SyntaxError(message, expected, found, location) {\r\n this.message = message;\r\n this.expected = expected;\r\n this.found = found;\r\n this.location = location;\r\n this.name = \"SyntaxError\";\r\n\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(this, peg$SyntaxError);\r\n }\r\n }\r\n\r\n peg$subclass(peg$SyntaxError, Error);\r\n\r\n peg$SyntaxError.buildMessage = function (expected, found) {\r\n var DESCRIBE_EXPECTATION_FNS = {\r\n literal: function (expectation) {\r\n return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";\r\n },\r\n\r\n \"class\": function (expectation) {\r\n var escapedParts = \"\",\r\n i;\r\n\r\n for (i = 0; i < expectation.parts.length; i++) {\r\n escapedParts += expectation.parts[i] instanceof Array ?\r\n classEscape(expectation.parts[i][0]) + \"-\" + classEscape(expectation.parts[i][1]) :\r\n classEscape(expectation.parts[i]);\r\n }\r\n\r\n return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";\r\n },\r\n\r\n any: function (expectation) {\r\n return \"any character\";\r\n },\r\n\r\n end: function (expectation) {\r\n return \"end of input\";\r\n },\r\n\r\n other: function (expectation) {\r\n return expectation.description;\r\n }\r\n };\r\n\r\n function hex(ch) {\r\n return ch.charCodeAt(0).toString(16).toUpperCase();\r\n }\r\n\r\n function literalEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function classEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\\]/g, '\\\\]')\r\n .replace(/\\^/g, '\\\\^')\r\n .replace(/-/g, '\\\\-')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function describeExpectation(expectation) {\r\n return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\r\n }\r\n\r\n function describeExpected(expected) {\r\n var descriptions = new Array(expected.length),\r\n i, j;\r\n\r\n for (i = 0; i < expected.length; i++) {\r\n descriptions[i] = describeExpectation(expected[i]);\r\n }\r\n\r\n descriptions.sort();\r\n\r\n if (descriptions.length > 0) {\r\n for (i = 1, j = 1; i < descriptions.length; i++) {\r\n if (descriptions[i - 1] !== descriptions[i]) {\r\n descriptions[j] = descriptions[i];\r\n j++;\r\n }\r\n }\r\n descriptions.length = j;\r\n }\r\n\r\n switch (descriptions.length) {\r\n case 1:\r\n return descriptions[0];\r\n\r\n case 2:\r\n return descriptions[0] + \" or \" + descriptions[1];\r\n\r\n default:\r\n return descriptions.slice(0, -1).join(\", \") +\r\n \", or \" +\r\n descriptions[descriptions.length - 1];\r\n }\r\n }\r\n\r\n function describeFound(found) {\r\n return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";\r\n }\r\n\r\n return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\r\n };\r\n\r\n function peg$parse(input, options) {\r\n options = options !== void 0 ? options : {};\r\n\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n var nOpenParentheses = input.split('(').length - 1;\r\n var nCloseParentheses = input.split(')').length - 1;\r\n\r\n if (nOpenParentheses !== nCloseParentheses) {\r\n throw peg$buildSimpleError('The number of opening parentheses does not match the number of closing parentheses.', 0);\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n var peg$FAILED = {},\r\n\r\n peg$startRuleFunctions = {\r\n chain: peg$parsechain\r\n },\r\n peg$startRuleFunction = peg$parsechain,\r\n\r\n peg$c0 = function (s) {\r\n var branches = [];\r\n var rings = [];\r\n\r\n for (var i = 0; i < s[1].length; i++) {\r\n branches.push(s[1][i]);\r\n }\r\n\r\n\r\n for (var i = 0; i < s[2].length; i++) {\r\n var bond = (s[2][i][0]) ? s[2][i][0] : '-';\r\n rings.push({\r\n 'bond': bond,\r\n 'id': s[2][i][1]\r\n });\r\n }\r\n\r\n for (var i = 0; i < s[3].length; i++) {\r\n branches.push(s[3][i]);\r\n }\r\n\r\n for (var i = 0; i < s[6].length; i++) {\r\n branches.push(s[6][i]);\r\n }\r\n\r\n return {\r\n 'atom': s[0],\r\n 'isBracket': s[0].element ? true : false,\r\n 'branches': branches,\r\n 'branchCount': branches.length,\r\n 'ringbonds': rings,\r\n 'ringbondCount': rings.length,\r\n 'bond': s[4] ? s[4] : '-',\r\n 'next': s[5],\r\n 'hasNext': s[5] ? true : false\r\n }\r\n\r\n return s;\r\n },\r\n peg$c1 = \"(\",\r\n peg$c2 = peg$literalExpectation(\"(\", false),\r\n peg$c3 = \")\",\r\n peg$c4 = peg$literalExpectation(\")\", false),\r\n peg$c5 = function (b) {\r\n var bond = (b[1]) ? b[1] : '-';\r\n b[2].branchBond = bond;\r\n return b[2]\r\n },\r\n peg$c6 = function (a) {\r\n return a;\r\n },\r\n peg$c7 = /^[\\-=#$:\\/\\\\.]/,\r\n peg$c8 = peg$classExpectation([\"-\", \"=\", \"#\", \"$\", \":\", \"/\", \"\\\\\", \".\"], false, false),\r\n peg$c9 = function (b) {\r\n return b;\r\n },\r\n peg$c10 = \"[\",\r\n peg$c11 = peg$literalExpectation(\"[\", false),\r\n peg$c12 = \"se\",\r\n peg$c13 = peg$literalExpectation(\"se\", false),\r\n peg$c14 = \"as\",\r\n peg$c15 = peg$literalExpectation(\"as\", false),\r\n peg$c16 = \"]\",\r\n peg$c17 = peg$literalExpectation(\"]\", false),\r\n peg$c18 = function (b) {\r\n return {\r\n 'isotope': b[1],\r\n 'element': b[2],\r\n 'chirality': b[3],\r\n 'hcount': b[4],\r\n 'charge': b[5],\r\n 'class': b[6]\r\n }\r\n },\r\n peg$c19 = \"B\",\r\n peg$c20 = peg$literalExpectation(\"B\", false),\r\n peg$c21 = \"r\",\r\n peg$c22 = peg$literalExpectation(\"r\", false),\r\n peg$c23 = \"C\",\r\n peg$c24 = peg$literalExpectation(\"C\", false),\r\n peg$c25 = \"l\",\r\n peg$c26 = peg$literalExpectation(\"l\", false),\r\n peg$c27 = /^[NOPSFI]/,\r\n peg$c28 = peg$classExpectation([\"N\", \"O\", \"P\", \"S\", \"F\", \"I\"], false, false),\r\n peg$c29 = function (o) {\r\n if (o.length > 1) return o.join('');\r\n return o;\r\n },\r\n peg$c30 = /^[bcnops]/,\r\n peg$c31 = peg$classExpectation([\"b\", \"c\", \"n\", \"o\", \"p\", \"s\"], false, false),\r\n peg$c32 = \"*\",\r\n peg$c33 = peg$literalExpectation(\"*\", false),\r\n peg$c34 = function (w) {\r\n return w;\r\n },\r\n peg$c35 = /^[A-Z]/,\r\n peg$c36 = peg$classExpectation([\r\n [\"A\", \"Z\"]\r\n ], false, false),\r\n peg$c37 = /^[a-z]/,\r\n peg$c38 = peg$classExpectation([\r\n [\"a\", \"z\"]\r\n ], false, false),\r\n peg$c39 = function (e) {\r\n return e.join('');\r\n },\r\n peg$c40 = \"%\",\r\n peg$c41 = peg$literalExpectation(\"%\", false),\r\n peg$c42 = /^[1-9]/,\r\n peg$c43 = peg$classExpectation([\r\n [\"1\", \"9\"]\r\n ], false, false),\r\n peg$c44 = /^[0-9]/,\r\n peg$c45 = peg$classExpectation([\r\n [\"0\", \"9\"]\r\n ], false, false),\r\n peg$c46 = function (r) {\r\n if (r.length == 1) return Number(r);\r\n return Number(r.join('').replace('%', ''));\r\n },\r\n peg$c47 = \"@\",\r\n peg$c48 = peg$literalExpectation(\"@\", false),\r\n peg$c49 = \"TH\",\r\n peg$c50 = peg$literalExpectation(\"TH\", false),\r\n peg$c51 = /^[12]/,\r\n peg$c52 = peg$classExpectation([\"1\", \"2\"], false, false),\r\n peg$c53 = \"AL\",\r\n peg$c54 = peg$literalExpectation(\"AL\", false),\r\n peg$c55 = \"SP\",\r\n peg$c56 = peg$literalExpectation(\"SP\", false),\r\n peg$c57 = /^[1-3]/,\r\n peg$c58 = peg$classExpectation([\r\n [\"1\", \"3\"]\r\n ], false, false),\r\n peg$c59 = \"TB\",\r\n peg$c60 = peg$literalExpectation(\"TB\", false),\r\n peg$c61 = \"OH\",\r\n peg$c62 = peg$literalExpectation(\"OH\", false),\r\n peg$c63 = function (c) {\r\n if (!c[1]) return '@';\r\n if (c[1] == '@') return '@@';\r\n\r\n return c[1].join('').replace(',', '');\r\n },\r\n peg$c64 = function (c) {\r\n return c;\r\n },\r\n peg$c65 = \"+\",\r\n peg$c66 = peg$literalExpectation(\"+\", false),\r\n peg$c67 = function (c) {\r\n if (!c[1]) return 1;\r\n if (c[1] != '+') return Number(c[1].join(''));\r\n return 2;\r\n },\r\n peg$c68 = \"-\",\r\n peg$c69 = peg$literalExpectation(\"-\", false),\r\n peg$c70 = function (c) {\r\n if (!c[1]) return -1;\r\n if (c[1] != '-') return -Number(c[1].join(''));\r\n return -2;\r\n },\r\n peg$c71 = \"H\",\r\n peg$c72 = peg$literalExpectation(\"H\", false),\r\n peg$c73 = function (h) {\r\n if (h[1]) return Number(h[1]);\r\n return 1;\r\n },\r\n peg$c74 = \":\",\r\n peg$c75 = peg$literalExpectation(\":\", false),\r\n peg$c76 = /^[0]/,\r\n peg$c77 = peg$classExpectation([\"0\"], false, false),\r\n peg$c78 = function (c) {\r\n return Number(c[1][0] + c[1][1].join(''));\r\n },\r\n peg$c79 = function (i) {\r\n return Number(i.join(''));\r\n },\r\n\r\n peg$currPos = 0,\r\n peg$savedPos = 0,\r\n peg$posDetailsCache = [{\r\n line: 1,\r\n column: 1\r\n }],\r\n peg$maxFailPos = 0,\r\n peg$maxFailExpected = [],\r\n peg$silentFails = 0,\r\n\r\n peg$result;\r\n\r\n if (\"startRule\" in options) {\r\n if (!(options.startRule in peg$startRuleFunctions)) {\r\n throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");\r\n }\r\n\r\n peg$startRuleFunction = peg$startRuleFunctions[options.startRule];\r\n }\r\n\r\n function text() {\r\n return input.substring(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function location() {\r\n return peg$computeLocation(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function expected(description, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildStructuredError(\r\n [peg$otherExpectation(description)],\r\n input.substring(peg$savedPos, peg$currPos),\r\n location\r\n );\r\n }\r\n\r\n function error(message, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildSimpleError(message, location);\r\n }\r\n\r\n function peg$literalExpectation(text, ignoreCase) {\r\n return {\r\n type: \"literal\",\r\n text: text,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$classExpectation(parts, inverted, ignoreCase) {\r\n return {\r\n type: \"class\",\r\n parts: parts,\r\n inverted: inverted,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$anyExpectation() {\r\n return {\r\n type: \"any\"\r\n };\r\n }\r\n\r\n function peg$endExpectation() {\r\n return {\r\n type: \"end\"\r\n };\r\n }\r\n\r\n function peg$otherExpectation(description) {\r\n return {\r\n type: \"other\",\r\n description: description\r\n };\r\n }\r\n\r\n function peg$computePosDetails(pos) {\r\n var details = peg$posDetailsCache[pos],\r\n p;\r\n\r\n if (details) {\r\n return details;\r\n } else {\r\n p = pos - 1;\r\n while (!peg$posDetailsCache[p]) {\r\n p--;\r\n }\r\n\r\n details = peg$posDetailsCache[p];\r\n details = {\r\n line: details.line,\r\n column: details.column\r\n };\r\n\r\n while (p < pos) {\r\n if (input.charCodeAt(p) === 10) {\r\n details.line++;\r\n details.column = 1;\r\n } else {\r\n details.column++;\r\n }\r\n\r\n p++;\r\n }\r\n\r\n peg$posDetailsCache[pos] = details;\r\n return details;\r\n }\r\n }\r\n\r\n function peg$computeLocation(startPos, endPos) {\r\n var startPosDetails = peg$computePosDetails(startPos),\r\n endPosDetails = peg$computePosDetails(endPos);\r\n\r\n return {\r\n start: {\r\n offset: startPos,\r\n line: startPosDetails.line,\r\n column: startPosDetails.column\r\n },\r\n end: {\r\n offset: endPos,\r\n line: endPosDetails.line,\r\n column: endPosDetails.column\r\n }\r\n };\r\n }\r\n\r\n function peg$fail(expected) {\r\n if (peg$currPos < peg$maxFailPos) {\r\n return;\r\n }\r\n\r\n if (peg$currPos > peg$maxFailPos) {\r\n peg$maxFailPos = peg$currPos;\r\n peg$maxFailExpected = [];\r\n }\r\n\r\n peg$maxFailExpected.push(expected);\r\n }\r\n\r\n function peg$buildSimpleError(message, location) {\r\n return new peg$SyntaxError(message, null, null, location);\r\n }\r\n\r\n function peg$buildStructuredError(expected, found, location) {\r\n return new peg$SyntaxError(\r\n peg$SyntaxError.buildMessage(expected, found),\r\n expected,\r\n found,\r\n location\r\n );\r\n }\r\n\r\n function peg$parsechain() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n s2 = peg$parseatom();\r\n if (s2 !== peg$FAILED) {\r\n s3 = [];\r\n s4 = peg$parsebranch();\r\n while (s4 !== peg$FAILED) {\r\n s3.push(s4);\r\n s4 = peg$parsebranch();\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = [];\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n while (s5 !== peg$FAILED) {\r\n s4.push(s5);\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n s6 = peg$parsebranch();\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n s6 = peg$parsebranch();\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsechain();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = [];\r\n s9 = peg$parsebranch();\r\n while (s9 !== peg$FAILED) {\r\n s8.push(s9);\r\n s9 = peg$parsebranch();\r\n }\r\n if (s8 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c0(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebranch() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 40) {\r\n s2 = peg$c1;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c2);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parsebond();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = peg$parsechain();\r\n if (s4 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 41) {\r\n s5 = peg$c3;\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c4);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c5(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseatom() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseorganicsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsearomaticsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsebracketatom();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebond() {\r\n var s0, s1;\r\n s0 = peg$currPos;\r\n if (peg$c7.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n\r\n // Hack to resolve problem caused by:\r\n // O=C(N[C@@H](CC(O)=O)C(N[C@H](C1=CC=C(O)C=C1)C(N[C@@H](CC(O)=O)C(NCC(N[C@@H](C(N[C@@H]([C@H](C)CC(O)=O)C(N/C(C(O[C@H](C)[C@@H]2NC([C@H](CO)NC(C(O3)C3CCC)=O)=O)=O)=C\\\\\\\\C4=CNC5=C4C=CC=C5)=O)=O)[C@H](O)C(N)=O)=O)=O)=O)=O)[C@H](CC(O)=O)NC([C@@H](CC6=CNC7=C6C=CC=C7)NC2=O)=O\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n if (s1 === input.charAt(peg$currPos + 1)) {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n throw peg$buildSimpleError('The parser encountered a bond repetition.', peg$currPos + 1);\r\n }\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c8);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c9(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebracketatom() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 91) {\r\n s2 = peg$c10;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c11);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parseisotope();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c12) {\r\n s4 = peg$c12;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c13);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c14) {\r\n s4 = peg$c14;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c15);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsearomaticsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parseelementsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = peg$parsechiral();\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsehcount();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsecharge();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = peg$parseclass();\r\n if (s8 === peg$FAILED) {\r\n s8 = null;\r\n }\r\n if (s8 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 93) {\r\n s9 = peg$c16;\r\n peg$currPos++;\r\n } else {\r\n s9 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c17);\r\n }\r\n }\r\n if (s9 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8, s9];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c18(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseorganicsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 66) {\r\n s2 = peg$c19;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c20);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 114) {\r\n s3 = peg$c21;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c22);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 67) {\r\n s2 = peg$c23;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c24);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 108) {\r\n s3 = peg$c25;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c26);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c27.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c28);\r\n }\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c29(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsearomaticsymbol() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (peg$c30.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c31);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsewildcard() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 42) {\r\n s1 = peg$c32;\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c33);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c34(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseelementsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c35.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c36);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c37.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c38);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c39(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsering() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 37) {\r\n s2 = peg$c40;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c41);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c46(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsechiral() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s2 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s3 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c49) {\r\n s4 = peg$c49;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c50);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c53) {\r\n s4 = peg$c53;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c54);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c55) {\r\n s4 = peg$c55;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c56);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c57.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c58);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c59) {\r\n s4 = peg$c59;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c60);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c61) {\r\n s4 = peg$c61;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c62);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c63(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsecharge() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseposcharge();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsenegcharge();\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c64(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseposcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s2 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s3 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c67(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsenegcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s2 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s3 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c70(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsehcount() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 72) {\r\n s2 = peg$c71;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c72);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c73(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseclass() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 58) {\r\n s2 = peg$c74;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c75);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n if (peg$c76.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c77);\r\n }\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c78(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseisotope() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = null;\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c79(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n peg$result = peg$startRuleFunction();\r\n\r\n if (peg$result !== peg$FAILED && peg$currPos === input.length) {\r\n return peg$result;\r\n } else {\r\n if (peg$result !== peg$FAILED && peg$currPos < input.length) {\r\n peg$fail(peg$endExpectation());\r\n }\r\n\r\n throw peg$buildStructuredError(\r\n peg$maxFailExpected,\r\n peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,\r\n peg$maxFailPos < input.length ?\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) :\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n SyntaxError: peg$SyntaxError,\r\n parse: peg$parse\r\n };\r\n})();","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Vertex = require('./Vertex')\r\nconst RingConnection = require('./RingConnection')\r\n\r\n/** \r\n * A class representing a ring.\r\n * \r\n * @property {Number} id The id of this ring.\r\n * @property {Number[]} members An array containing the vertex ids of the ring members.\r\n * @property {Number[]} edges An array containing the edge ids of the edges between the ring members.\r\n * @property {Number[]} insiders An array containing the vertex ids of the vertices contained within the ring if it is a bridged ring.\r\n * @property {Number[]} neighbours An array containing the ids of neighbouring rings.\r\n * @property {Boolean} positioned A boolean indicating whether or not this ring has been positioned.\r\n * @property {Vector2} center The center of this ring.\r\n * @property {Ring[]} rings The rings contained within this ring if this ring is bridged.\r\n * @property {Boolean} isBridged A boolean whether or not this ring is bridged.\r\n * @property {Boolean} isPartOfBridged A boolean whether or not this ring is part of a bridge ring.\r\n * @property {Boolean} isSpiro A boolean whether or not this ring is part of a spiro.\r\n * @property {Boolean} isFused A boolean whether or not this ring is part of a fused ring.\r\n * @property {Number} centralAngle The central angle of this ring.\r\n * @property {Boolean} canFlip A boolean indicating whether or not this ring allows flipping of attached vertices to the inside of the ring.\r\n */\r\nclass Ring {\r\n /**\r\n * The constructor for the class Ring.\r\n *\r\n * @param {Number[]} members An array containing the vertex ids of the members of the ring to be created.\r\n */\r\n constructor(members) {\r\n this.id = null;\r\n this.members = members;\r\n this.edges = [];\r\n this.insiders = [];\r\n this.neighbours = [];\r\n this.positioned = false;\r\n this.center = new Vector2(0, 0);\r\n this.rings = [];\r\n this.isBridged = false;\r\n this.isPartOfBridged = false;\r\n this.isSpiro = false;\r\n this.isFused = false;\r\n this.centralAngle = 0.0;\r\n this.canFlip = true;\r\n }\r\n \r\n /**\r\n * Clones this ring and returns the clone.\r\n *\r\n * @returns {Ring} A clone of this ring.\r\n */\r\n clone() {\r\n let clone = new Ring(this.members);\r\n\r\n clone.id = this.id;\r\n clone.insiders = ArrayHelper.clone(this.insiders);\r\n clone.neighbours = ArrayHelper.clone(this.neighbours);\r\n clone.positioned = this.positioned;\r\n clone.center = this.center.clone();\r\n clone.rings = ArrayHelper.clone(this.rings);\r\n clone.isBridged = this.isBridged;\r\n clone.isPartOfBridged = this.isPartOfBridged;\r\n clone.isSpiro = this.isSpiro;\r\n clone.isFused = this.isFused;\r\n clone.centralAngle = this.centralAngle;\r\n clone.canFlip = this.canFlip;\r\n\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns the size (number of members) of this ring.\r\n *\r\n * @returns {Number} The size (number of members) of this ring.\r\n */\r\n getSize() {\r\n return this.members.length;\r\n }\r\n\r\n /**\r\n * Gets the polygon representation (an array of the ring-members positional vectors) of this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices representing the current molecule.\r\n * @returns {Vector2[]} An array of the positional vectors of the ring members.\r\n */\r\n getPolygon(vertices) {\r\n let polygon = [];\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n polygon.push(vertices[this.members[i]].position);\r\n }\r\n\r\n return polygon;\r\n }\r\n\r\n /**\r\n * Returns the angle of this ring in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n return Math.PI - this.centralAngle;\r\n }\r\n\r\n /**\r\n * Loops over the members of this ring from a given start position in a direction opposite to the vertex id passed as the previousId.\r\n *\r\n * @param {Vertex[]} vertices The vertices associated with the current molecule.\r\n * @param {Function} callback A callback with the current vertex id as a parameter.\r\n * @param {Number} startVertexId The vertex id of the start vertex.\r\n * @param {Number} previousVertexId The vertex id of the previous vertex (the loop calling the callback function will run in the opposite direction of this vertex).\r\n */\r\n eachMember(vertices, callback, startVertexId, previousVertexId) {\r\n startVertexId = startVertexId || startVertexId === 0 ? startVertexId : this.members[0];\r\n let current = startVertexId;\r\n let max = 0;\r\n\r\n while (current != null && max < 100) {\r\n let prev = current;\r\n \r\n callback(prev);\r\n current = vertices[current].getNextInRing(vertices, this.id, previousVertexId);\r\n previousVertexId = prev;\r\n \r\n // Stop while loop when arriving back at the start vertex\r\n if (current == startVertexId) {\r\n current = null;\r\n }\r\n\r\n max++;\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array containing the neighbouring rings of this ring ordered by ring size.\r\n *\r\n * @param {RingConnection[]} ringConnections An array of ring connections associated with the current molecule.\r\n * @returns {Object[]} An array of neighbouring rings sorted by ring size. Example: { n: 5, neighbour: 1 }.\r\n */\r\n getOrderedNeighbours(ringConnections) {\r\n let orderedNeighbours = Array(this.neighbours.length);\r\n \r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n let vertices = RingConnection.getVertices(ringConnections, this.id, this.neighbours[i]);\r\n \r\n orderedNeighbours[i] = {\r\n n: vertices.length,\r\n neighbour: this.neighbours[i]\r\n };\r\n }\r\n\r\n orderedNeighbours.sort(function (a, b) {\r\n // Sort highest to lowest\r\n return b.n - a.n;\r\n });\r\n\r\n return orderedNeighbours;\r\n }\r\n\r\n /**\r\n * Check whether this ring is an implicitly defined benzene-like (e.g. C1=CC=CC=C1) with 6 members and 3 double bonds.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring is an implicitly defined benzene-like.\r\n */\r\n isBenzeneLike(vertices) {\r\n let db = this.getDoubleBondCount(vertices);\r\n let length = this.members.length;\r\n\r\n return db === 3 && length === 6 ||\r\n db === 2 && length === 5 ;\r\n }\r\n\r\n /**\r\n * Get the number of double bonds inside this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Number} The number of double bonds inside this ring.\r\n */\r\n getDoubleBondCount(vertices) {\r\n let doubleBondCount = 0;\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n let atom = vertices[this.members[i]].value;\r\n\r\n if (atom.bondType === '=' || atom.branchBond === '=') {\r\n doubleBondCount++;\r\n }\r\n }\r\n\r\n return doubleBondCount;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring contains a member with a given vertex id.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not this ring contains a member with the given vertex id.\r\n */\r\n contains(vertexId) {\r\n for (let i = 0; i < this.members.length; i++) {\r\n if (this.members[i] == vertexId) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n\r\nmodule.exports = Ring;","//@ts-check\r\nconst Vertex = require('./Vertex')\r\nconst Ring = require('./Ring')\r\n\r\n/** \r\n * A class representing a ring connection.\r\n * \r\n * @property {Number} id The id of this ring connection.\r\n * @property {Number} firstRingId A ring id.\r\n * @property {Number} secondRingId A ring id.\r\n * @property {Set} vertices A set containing the vertex ids participating in the ring connection.\r\n */\r\nclass RingConnection {\r\n /**\r\n * The constructor for the class RingConnection.\r\n *\r\n * @param {Ring} firstRing A ring.\r\n * @param {Ring} secondRing A ring.\r\n */\r\n constructor(firstRing, secondRing) {\r\n this.id = null;\r\n this.firstRingId = firstRing.id;\r\n this.secondRingId = secondRing.id;\r\n this.vertices = new Set();\r\n\r\n for (var m = 0; m < firstRing.members.length; m++) {\r\n let c = firstRing.members[m];\r\n\r\n for (let n = 0; n < secondRing.members.length; n++) {\r\n let d = secondRing.members[n];\r\n\r\n if (c === d) {\r\n this.addVertex(c);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adding a vertex to the ring connection.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n */\r\n addVertex(vertexId) {\r\n this.vertices.add(vertexId);\r\n }\r\n\r\n /**\r\n * Update the ring id of this ring connection that is not the ring id supplied as the second argument.\r\n *\r\n * @param {Number} ringId A ring id. The new ring id to be set.\r\n * @param {Number} otherRingId A ring id. The id that is NOT to be updated.\r\n */\r\n updateOther(ringId, otherRingId) {\r\n if (this.firstRingId === otherRingId) {\r\n this.secondRingId = ringId;\r\n } else {\r\n this.firstRingId = ringId;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.\r\n * \r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.\r\n */\r\n containsRing(ringId) {\r\n return this.firstRingId === ringId || this.secondRingId === ringId;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring connection is a bridge in a bridged ring.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.\r\n */\r\n isBridge(vertices) {\r\n if (this.vertices.size > 2) {\r\n return true;\r\n }\r\n\r\n for (let vertexId of this.vertices) {\r\n if(vertices[vertexId].value.rings.length > 2) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two rings are connected by a bridged bond.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.\r\n */\r\n static isBridge(ringConnections, vertices, firstRingId, secondRingId) {\r\n let ringConnection = null;\r\n \r\n for (let i = 0; i < ringConnections.length; i++) {\r\n ringConnection = ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return ringConnection.isBridge(vertices);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Retruns the neighbouring rings of a given ring.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array of ring ids of neighbouring rings.\r\n */\r\n static getNeighbours(ringConnections, ringId) {\r\n let neighbours = [];\r\n\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n \r\n if (ringConnection.firstRingId === ringId) {\r\n neighbours.push(ringConnection.secondRingId);\r\n } else if (ringConnection.secondRingId === ringId) {\r\n neighbours.push(ringConnection.firstRingId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Returns an array of vertex ids associated with a given ring connection.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Number[]} An array of vertex ids associated with the ring connection.\r\n */\r\n static getVertices(ringConnections, firstRingId, secondRingId) {\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return [...ringConnection.vertices];\r\n }\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = RingConnection","//@ts-check\r\nconst Graph = require('./Graph')\r\n\r\n/** A class encapsulating the functionality to find the smallest set of smallest rings in a graph. */\r\nclass SSSR {\r\n /**\r\n * Returns an array containing arrays, each representing a ring from the smallest set of smallest rings in the graph.\r\n * \r\n * @param {Graph} graph A Graph object.\r\n * @param {Boolean} [experimental=false] Whether or not to use experimental SSSR.\r\n * @returns {Array[]} An array containing arrays, each representing a ring from the smallest set of smallest rings in the group.\r\n */\r\n static getRings(graph, experimental=false) {\r\n let adjacencyMatrix = graph.getComponentsAdjacencyMatrix();\r\n if (adjacencyMatrix.length === 0) {\r\n return null;\r\n }\r\n\r\n let connectedComponents = Graph.getConnectedComponents(adjacencyMatrix);\r\n let rings = Array();\r\n\r\n for (var i = 0; i < connectedComponents.length; i++) {\r\n let connectedComponent = connectedComponents[i];\r\n let ccAdjacencyMatrix = graph.getSubgraphAdjacencyMatrix([...connectedComponent]);\r\n\r\n let arrBondCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n let arrRingCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n arrRingCount[j] = 0;\r\n arrBondCount[j] = 0;\r\n\r\n for (var k = 0; k < ccAdjacencyMatrix[j].length; k++) {\r\n arrBondCount[j] += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n // Get the edge number and the theoretical number of rings in SSSR\r\n let nEdges = 0;\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n for (var k = j + 1; k < ccAdjacencyMatrix.length; k++) {\r\n nEdges += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n let nSssr = nEdges - ccAdjacencyMatrix.length + 1;\r\n\r\n // console.log(nEdges, ccAdjacencyMatrix.length, nSssr);\r\n // console.log(SSSR.getEdgeList(ccAdjacencyMatrix));\r\n // console.log(ccAdjacencyMatrix);\r\n\r\n // If all vertices have 3 incident edges, calculate with different formula (see Euler)\r\n let allThree = true;\r\n for (var j = 0; j < arrBondCount.length; j++) {\r\n if (arrBondCount[j] !== 3) {\r\n allThree = false;\r\n }\r\n }\r\n\r\n if (allThree) {\r\n nSssr = 2.0 + nEdges - ccAdjacencyMatrix.length;\r\n }\r\n\r\n // All vertices are part of one ring if theres only one ring.\r\n if (nSssr === 1) {\r\n rings.push([...connectedComponent]);\r\n continue;\r\n }\r\n \r\n if (experimental) {\r\n nSssr = 999;\r\n }\r\n\r\n let { d, pe, pe_prime } = SSSR.getPathIncludedDistanceMatrices(ccAdjacencyMatrix);\r\n let c = SSSR.getRingCandidates(d, pe, pe_prime);\r\n let sssr = SSSR.getSSSR(c, d, ccAdjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nSssr);\r\n\r\n for (var j = 0; j < sssr.length; j++) {\r\n let ring = Array(sssr[j].size);\r\n let index = 0;\r\n\r\n for (let val of sssr[j]) {\r\n // Get the original id of the vertex back\r\n ring[index++] = connectedComponent[val];\r\n }\r\n\r\n rings.push(ring);\r\n }\r\n }\r\n \r\n\r\n // So, for some reason, this would return three rings for C1CCCC2CC1CCCC2, which is wrong\r\n // As I don't have time to fix this properly, it will stay in. I'm sorry next person who works\r\n // on it. At that point it might be best to reimplement the whole SSSR thing...\r\n return rings;\r\n }\r\n\r\n /**\r\n * Creates a printable string from a matrix (2D array).\r\n * \r\n * @param {Array[]} matrix A 2D array.\r\n * @returns {String} A string representing the matrix.\r\n */\r\n static matrixToString(matrix) {\r\n let str = '';\r\n\r\n for (var i = 0; i < matrix.length; i++) {\r\n for (var j = 0; j < matrix[i].length; j++) {\r\n str += matrix[i][j] + ' ';\r\n }\r\n\r\n str += '\\n';\r\n }\r\n\r\n return str;\r\n }\r\n\r\n /**\r\n * Returnes the two path-included distance matrices used to find the sssr.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Object} The path-included distance matrices. { p1, p2 }\r\n */\r\n static getPathIncludedDistanceMatrices(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let d = Array(length);\r\n let pe = Array(length);\r\n let pe_prime = Array(length);\r\n var l = 0;\r\n var m = 0;\r\n var n = 0;\r\n\r\n var i = length;\r\n while (i--) {\r\n d[i] = Array(length);\r\n pe[i] = Array(length);\r\n pe_prime[i] = Array(length);\r\n\r\n var j = length;\r\n while (j--) {\r\n d[i][j] = (i === j || adjacencyMatrix[i][j] === 1) ? adjacencyMatrix[i][j] : Number.POSITIVE_INFINITY;\r\n\r\n if (d[i][j] === 1) {\r\n pe[i][j] = [[[i, j]]];\r\n } else {\r\n pe[i][j] = Array();\r\n }\r\n\r\n pe_prime[i][j] = Array();\r\n }\r\n }\r\n\r\n var k = length;\r\n var j;\r\n while (k--) {\r\n i = length;\r\n while (i--) {\r\n j = length;\r\n while (j--) {\r\n const previousPathLength = d[i][j];\r\n const newPathLength = d[i][k] + d[k][j];\r\n\r\n if (previousPathLength > newPathLength) {\r\n var l, m, n;\r\n if (previousPathLength === newPathLength + 1) {\r\n pe_prime[i][j] = [pe[i][j].length];\r\n l = pe[i][j].length\r\n while (l--) {\r\n pe_prime[i][j][l] = [pe[i][j][l].length];\r\n m = pe[i][j][l].length\r\n while (m--) {\r\n pe_prime[i][j][l][m] = [pe[i][j][l][m].length];\r\n n = pe[i][j][l][m].length;\r\n while (n--) {\r\n pe_prime[i][j][l][m][n] = [pe[i][j][l][m][0], pe[i][j][l][m][1]];\r\n }\r\n }\r\n }\r\n } else {\r\n pe_prime[i][j] = Array();\r\n }\r\n\r\n d[i][j] = newPathLength;\r\n\r\n pe[i][j] = [[]];\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[k][j][0][l]);\r\n }\r\n } else if (previousPathLength === newPathLength) {\r\n if (pe[i][k].length && pe[k][j].length) {\r\n var l;\r\n if (pe[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j][0] = tmp\r\n }\r\n }\r\n } else if (previousPathLength === newPathLength - 1) {\r\n var l;\r\n if (pe_prime[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j][0] = tmp;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n d: d,\r\n pe: pe,\r\n pe_prime: pe_prime\r\n };\r\n }\r\n\r\n /**\r\n * Get the ring candidates from the path-included distance matrices.\r\n * \r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @returns {Array[]} The ring candidates.\r\n */\r\n static getRingCandidates(d, pe, pe_prime) {\r\n let length = d.length;\r\n let candidates = Array();\r\n let c = 0;\r\n\r\n for (let i = 0; i < length; i++) {\r\n for (let j = 0; j < length; j++) {\r\n if (d[i][j] === 0 || (pe[i][j].length === 1 && pe_prime[i][j] === 0)) {\r\n continue;\r\n } else {\r\n // c is the number of vertices in the cycle.\r\n if (pe_prime[i][j].length !== 0) {\r\n c = 2 * (d[i][j] + 0.5);\r\n } else {\r\n c = 2 * d[i][j];\r\n }\r\n\r\n if (c !== Infinity) {\r\n candidates.push([c, pe[i][j], pe_prime[i][j]]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Candidates have to be sorted by c\r\n candidates.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n\r\n return candidates;\r\n }\r\n\r\n /**\r\n * Searches the candidates for the smallest set of smallest rings.\r\n * \r\n * @param {Array[]} c The candidates.\r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @param {Number} nsssr The theoretical number of rings in the graph.\r\n * @returns {Set[]} The smallest set of smallest rings.\r\n */\r\n static getSSSR(c, d, adjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nsssr) {\r\n let cSssr = Array();\r\n let allBonds = Array();\r\n\r\n for (let i = 0; i < c.length; i++) {\r\n if (c[i][0] % 2 !== 0) {\r\n for (let j = 0; j < c[i][2].length; j++) {\r\n let bonds = c[i][1][0].concat(c[i][2][j]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n } else {\r\n for (let j = 0; j < c[i][1].length - 1; j++) {\r\n let bonds = c[i][1][j].concat(c[i][1][j + 1]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return cSssr;\r\n }\r\n\r\n /**\r\n * Returns the number of edges in a graph defined by an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of edges in the graph defined by the adjacency matrix.\r\n */\r\n static getEdgeCount(adjacencyMatrix) {\r\n let edgeCount = 0;\r\n let length = adjacencyMatrix.length;\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeCount++;\r\n }\r\n }\r\n }\r\n\r\n return edgeCount;\r\n }\r\n\r\n /**\r\n * Returns an edge list constructed form an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Array[]} An edge list. E.g. [ [ 0, 1 ], ..., [ 16, 2 ] ]\r\n */\r\n static getEdgeList(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let edgeList = Array();\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeList.push([i, j]);\r\n }\r\n }\r\n }\r\n\r\n return edgeList;\r\n }\r\n\r\n /**\r\n * Return a set of vertex indices contained in an array of bonds.\r\n * \r\n * @param {Array} bonds An array of bonds. A bond is defined as [ sourceVertexId, targetVertexId ].\r\n * @returns {Set} An array of vertices.\r\n */\r\n static bondsToAtoms(bonds) {\r\n let atoms = new Set();\r\n\r\n var i = bonds.length;\r\n while (i--) {\r\n atoms.add(bonds[i][0]);\r\n atoms.add(bonds[i][1]);\r\n }\r\n return atoms;\r\n }\r\n\r\n /**\r\n * Returns the number of bonds within a set of atoms.\r\n * \r\n * @param {Set} atoms An array of atom ids.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of bonds in a set of atoms.\r\n */\r\n static getBondCount(atoms, adjacencyMatrix) {\r\n let count = 0;\r\n for (let u of atoms) {\r\n for (let v of atoms) {\r\n if (u === v) {\r\n continue;\r\n }\r\n count += adjacencyMatrix[u][v]\r\n }\r\n }\r\n\r\n return count / 2;\r\n }\r\n\r\n /**\r\n * Checks whether or not a given path already exists in an array of paths.\r\n * \r\n * @param {Set[]} pathSets An array of sets each representing a path.\r\n * @param {Set} pathSet A set representing a path.\r\n * @param {Array[]} bonds The bonds associated with the current path.\r\n * @param {Array[]} allBonds All bonds currently associated with rings in the SSSR set.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @returns {Boolean} A boolean indicating whether or not a give path is contained within a set.\r\n */\r\n static pathSetsContain(pathSets, pathSet, bonds, allBonds, arrBondCount, arrRingCount) {\r\n var i = pathSets.length;\r\n while (i--) {\r\n if (SSSR.isSupersetOf(pathSet, pathSets[i])) {\r\n return true;\r\n }\r\n\r\n if (pathSets[i].size !== pathSet.size) {\r\n continue;\r\n }\r\n\r\n if (SSSR.areSetsEqual(pathSets[i], pathSet)) {\r\n return true;\r\n }\r\n }\r\n\r\n // Check if the edges from the candidate are already all contained within the paths of the set of paths.\r\n // TODO: For some reason, this does not replace the isSupersetOf method above -> why?\r\n let count = 0;\r\n let allContained = false;\r\n i = bonds.length;\r\n while (i--) {\r\n var j = allBonds.length;\r\n while (j--) {\r\n if (bonds[i][0] === allBonds[j][0] && bonds[i][1] === allBonds[j][1] ||\r\n bonds[i][1] === allBonds[j][0] && bonds[i][0] === allBonds[j][1]) {\r\n count++;\r\n }\r\n\r\n if (count === bonds.length) {\r\n allContained = true;\r\n }\r\n }\r\n }\r\n\r\n // If all the bonds and thus vertices are already contained within other rings\r\n // check if there's one vertex with ringCount < bondCount\r\n let specialCase = false;\r\n if (allContained) {\r\n for (let element of pathSet) {\r\n if (arrRingCount[element] < arrBondCount[element]) {\r\n specialCase = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (allContained && !specialCase) {\r\n return true;\r\n }\r\n\r\n // Update the ring counts for the vertices\r\n for (let element of pathSet) {\r\n arrRingCount[element]++;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two sets are equal (contain the same elements).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not the two sets are equal.\r\n */\r\n static areSetsEqual(setA, setB) {\r\n if (setA.size !== setB.size) {\r\n return false;\r\n }\r\n\r\n for (let element of setA) {\r\n if (!setB.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Checks whether or not a set (setA) is a superset of another set (setB).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not setB is a superset of setA.\r\n */\r\n static isSupersetOf(setA, setB) {\r\n for (var element of setB) {\r\n if (!setA.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\nmodule.exports = SSSR;","//@ts-check\r\n\r\nclass SequenceType {\r\n\r\n static get VALUES() {\r\n return {\r\n LINEAR: \"linear\",\r\n CYCLIC: \"cyclic\",\r\n BRANCH: \"branched\",\r\n BRANCH_CYCLIC: \"branch-cyclic\",\r\n LINEAR_POLYKETIDE: \"linear-polyketide\",\r\n CYCLIC_POLYKETIDE: \"cyclic-polyketide\",\r\n OTHER: \"other\",\r\n }\r\n }\r\n\r\n static getTypeFromValues(isCyclic, isBranch, isOther) {\r\n if (isOther) { return this.VALUES.OTHER;}\r\n if (!isCyclic && !isBranch) {\r\n return this.VALUES.LINEAR;\r\n } else if(isCyclic && !isBranch) {\r\n return this.VALUES.CYCLIC;\r\n } else if (!isCyclic) {\r\n return this.VALUES.BRANCH;\r\n } else {\r\n return this.VALUES.BRANCH_CYCLIC;\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = SequenceType;\r\n","//@ts-check\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst VertexState = require('./VertexState');\r\nconst Neighbour = require('./Neighbour');\r\nconst Direction = require('./Direction');\r\n\r\nclass SmallGraph {\r\n\r\n constructor() {\r\n this._nodes = [];\r\n this.isOther = false;\r\n this._branch = false;\r\n this.isCyclic = false;\r\n this.isBranched = false;\r\n this.sequenceType = SequenceType.VALUES.LINEAR;\r\n this._nodeOnRing = null;\r\n }\r\n\r\n addVertex(node) {\r\n this._nodes.push(node);\r\n }\r\n\r\n addNeighbour(nodeId, neighbour, direction) {\r\n this._nodes[nodeId].addNeighbour(new Neighbour(neighbour, direction));\r\n }\r\n\r\n dfsInitialization() {\r\n this._nodes.forEach(e => e.vertexState = VertexState.VALUES.NOT_FOUND);\r\n }\r\n\r\n getSourceNode() {\r\n let ends = [];\r\n for (let index = 0; index < this._nodes.length; ++index) {\r\n if (this._nodes[index].neighbours.length === 1) {\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.C) {\r\n return this._nodes[index];\r\n }\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.POLYKETIDE) {\r\n return this._nodes[index];\r\n }\r\n ends.push(this._nodes[index]);\r\n }\r\n }\r\n if (ends.length > 0) {\r\n return ends[0];\r\n }\r\n return null;\r\n }\r\n\r\n oneCyclic() {\r\n if (this._nodes.length === 0) {\r\n return false;\r\n }\r\n this.dfsInitialization();\r\n this.isCyclic = false;\r\n this.dfsCyclic(this._nodes[0], -1);\r\n }\r\n\r\n dfsCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = vertex;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.neighbours.length; ++i) {\r\n if (vertexFromId !== vertex.neighbours[i].neighbour) {\r\n this.dfsCyclic(this._nodes[vertex.neighbours[i].neighbour], vertex.id);\r\n }\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSequenceStart() {\r\n if (this._nodes.length === 0) {\r\n return;\r\n }\r\n this.dfsInitialization();\r\n this.sequence = \"\";\r\n if (this.isCyclic) {\r\n this.findRing(this._nodeOnRing);\r\n this.dfsSequenceCyclic(this._nodeOnRing);\r\n } else {\r\n let sourceNode = this.getSourceNode();\r\n if (sourceNode !== null) {\r\n this.dfsSequence(this.getSourceNode(), -1);\r\n } else {\r\n this.sequenceType = 'other';\r\n this.isOther = true;\r\n return;\r\n }\r\n }\r\n if (this.sequence.charAt(this.sequence.length - 1) === '-') {\r\n this.sequence = this.sequence.substr(0, this.sequence.length - 1);\r\n }\r\n this.sequenceType = SequenceType.getTypeFromValues(this.isCyclic, this.isBranched, this.isOther);\r\n }\r\n\r\n arrayContainsTimes(array, searchValue, times) {\r\n let cnt = 0;\r\n for (let index = 0; index < array.length; ++index) {\r\n if (array[index].neighbour === searchValue) {\r\n cnt++;\r\n if (cnt === times) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n findRing(start) {\r\n let queue = [];\r\n let firstPath = [start.id];\r\n let firstPass = true;\r\n queue.push(firstPath);\r\n while (queue.length !== 0) {\r\n let path = queue.pop();\r\n let last = path[path.length - 1];\r\n let node = this._nodes[last];\r\n if (node.id === start.id && !firstPass) {\r\n if (path.length === 3 && path[0] === path[2] && !this.arrayContainsTimes(this._nodes[path[0]].neighbours, path[1], 2)) {\r\n continue;\r\n }\r\n path.forEach(v => this._nodes[v].onRing = true);\r\n continue;\r\n }\r\n node.neighbours.forEach(\r\n neighbour => {\r\n if (!path.some(e => e === neighbour.neighbour) || neighbour.neighbour === start.id) {\r\n let newPath = [...path];\r\n newPath.push(neighbour.neighbour);\r\n queue.push(newPath);\r\n }\r\n }\r\n );\r\n firstPass = false;\r\n }\r\n }\r\n\r\n sortByRingPreference(array) {\r\n let sortedArray = [...array];\r\n sortedArray.sort((a, b) => {\r\n if (this._nodes[a.neighbour].onRing === this._nodes[b.neighbour].onRing) {\r\n if (a.direction > b.direction) {\r\n return -1;\r\n } else if (a.direction < b.direction) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n } else if (this._nodes[a.neighbour].onRing) {\r\n return 1;\r\n } else {\r\n return -1;\r\n }\r\n });\r\n return sortedArray;\r\n }\r\n\r\n dfsSequenceCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n let sortedNeighbours = this.sortByRingPreference(vertex.neighbours);\r\n for (let index = 0; index < sortedNeighbours.length; ++index) {\r\n if (vertexFromId === sortedNeighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequenceCyclic(this._nodes[sortedNeighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n printVertex(vertexId) {\r\n this.sequence += `[${vertexId}]`;\r\n }\r\n\r\n printDash() {\r\n if (']' === this.sequence[this.sequence.length - 1]) {\r\n this.sequence += '-';\r\n }\r\n }\r\n\r\n printLeftBrace(vertex) {\r\n if (vertex.neighbours.length > 2) {\r\n if (this.isBranched) {\r\n this.isOther = true;\r\n }\r\n this.sequence += '\\\\(';\r\n this._branch = true;\r\n this.isBranched = true;\r\n }\r\n }\r\n\r\n printRightBrace() {\r\n if (this._branch) {\r\n this.sequence += '\\\\)';\r\n this._branch = false;\r\n }\r\n }\r\n\r\n dfsSequence(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n for (let index = 0; index < vertex.neighbours.length; ++index) {\r\n if (vertexFromId === vertex.neighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequence(this._nodes[vertex.neighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n}\r\n\r\nmodule.exports = SmallGraph;\r\n","// we use the drawer to do all the preprocessing. then we take over the drawing\r\n// portion to output to svg\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Atom = require('./Atom');\r\nconst Drawer = require('./Drawer');\r\nconst Graph = require('./Graph');\r\nconst Line = require('./Line');\r\nconst SvgWrapper = require('./SvgWrapper');\r\nconst ThemeManager = require('./ThemeManager');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgDrawer {\r\n constructor(options) {\r\n this.preprocessor = new Drawer(options);\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to an svg element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML svg element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n\r\n * @returns {Oject} The dimensions of the drawing in { width, height }\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n let preprocessor = this.preprocessor;\r\n\r\n preprocessor.initDraw(data, themeName, infoOnly);\r\n\r\n if (!infoOnly) {\r\n this.themeManager = new ThemeManager(this.preprocessor.opts.themes, themeName);\r\n this.svgWrapper = new SvgWrapper(this.themeManager, target, this.preprocessor.opts);\r\n }\r\n\r\n preprocessor.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.svgWrapper.determineDimensions(preprocessor.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(preprocessor.opts.debug);\r\n this.drawVertices(preprocessor.opts.debug);\r\n\r\n if (preprocessor.opts.debug) {\r\n console.log(preprocessor.graph);\r\n console.log(preprocessor.rings);\r\n console.log(preprocessor.ringConnections);\r\n }\r\n\r\n return this.svgWrapper.constructSvg();\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let preprocessor = this.preprocessor,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n drawn = Array(this.preprocessor.graph.edges.length);\r\n\r\n drawn.fill(false);\r\n\r\n graph.traverseBF(0, vertex => {\r\n let edges = graph.getEdges(vertex.id);\r\n for (var i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n this.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let ring = rings[i];\r\n\r\n if (preprocessor.isRingAromatic(ring)) {\r\n this.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bond.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n svgWrapper = this.svgWrapper,\r\n edge = preprocessor.graph.edges[edgeId],\r\n vertexA = preprocessor.graph.vertices[edge.sourceId],\r\n vertexB = preprocessor.graph.vertices[edge.targetId],\r\n elementA = vertexA.value.element,\r\n elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && preprocessor.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position,\r\n b = vertexB.position,\r\n normals = preprocessor.getEdgeNormals(edge),\r\n // Create a point on each side of the line\r\n sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || preprocessor.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && preprocessor.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = preprocessor.areVerticesInSameRing(vertexA, vertexB);\r\n let s = preprocessor.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(opts.bondSpacing);\r\n normals[1].multiplyScalar(opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line = null;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n }\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n // preprocessor.canvasWrapper.drawLine(line, true);\r\n svgWrapper.drawLine(line, true);\r\n } else {\r\n // preprocessor.canvasWrapper.drawLine(line);\r\n svgWrapper.drawLine(line);\r\n }\r\n\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((edge.center || vertexA.isTerminal() && vertexB.isTerminal()) ||\r\n (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1)) {\r\n this.multiplyNormals(normals, opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB),\r\n lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n } else if ((s.sideCount[0] > s.sideCount[1]) ||\r\n (s.totalSideCount[0] > s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((s.sideCount[0] < s.sideCount[1]) ||\r\n (s.totalSideCount[0] <= s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n svgWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else if (edge.wedge === 'down') {\r\n svgWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else {\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n svgWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n svgWrapper = this.svgWrapper;\r\n\r\n var i = graph.vertices.length;\r\n for (var i = 0; i < graph.vertices.length; i++) {\r\n let vertex = graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(graph.vertices);\r\n let isTerminal = opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (opts.atomVisualization === 'allballs') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || graph.vertices.length === 1) {\r\n if (opts.atomVisualization === 'default') {\r\n svgWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (opts.atomVisualization === 'balls') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = graph.vertices[vertex.neighbours[0]].position;\r\n let b = graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n svgWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (opts.debug) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let center = rings[i].center;\r\n svgWrapper.drawDebugPoint(center.x, center.y, 'r: ' + rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.preprocessor.getTotalOverlapScore();\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n return this.preprocessor.getMolecularFormula();\r\n }\r\n\r\n /**\r\n * @param {Array} normals list of normals to multiply\r\n * @param {Number} spacing value to multiply normals by\r\n */\r\n multiplyNormals(normals, spacing) {\r\n normals[0].multiplyScalar(spacing);\r\n normals[1].multiplyScalar(spacing);\r\n }\r\n}\r\n\r\nmodule.exports = SvgDrawer;","const {\r\n getChargeText\r\n} = require('./UtilityFunctions');\r\n\r\nconst Line = require('./Line');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgWrapper {\r\n constructor(themeManager, target, options) {\r\n this.svg = document.getElementById(target);\r\n this.opts = options;\r\n this.gradientId = 0;\r\n\r\n // maintain a list of line elements and their corresponding gradients\r\n // maintain a list of vertex elements\r\n this.paths = [];\r\n this.vertices = [];\r\n this.gradients = [];\r\n\r\n // maintain the offset for drawing purposes\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n // maintain the dimensions\r\n this.drawingWidth = 0;\r\n this.drawingHeight = 0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // for managing color schemes\r\n this.themeManager = themeManager;\r\n\r\n // create the mask\r\n this.maskElements = [];\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\r\n mask.setAttributeNS(null, 'x', 0);\r\n mask.setAttributeNS(null, 'y', 0);\r\n mask.setAttributeNS(null, 'width', '100%');\r\n mask.setAttributeNS(null, 'height', '100%');\r\n mask.setAttributeNS(null, 'fill', 'white');\r\n\r\n this.maskElements.push(mask);\r\n\r\n // clear the svg element\r\n while (this.svg.firstChild) {\r\n this.svg.removeChild(this.svg.firstChild);\r\n }\r\n }\r\n\r\n constructSvg() {\r\n // TODO: add the defs element to put gradients in\r\n let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'),\r\n masks = document.createElementNS('http://www.w3.org/2000/svg', 'mask'),\r\n style = document.createElementNS('http://www.w3.org/2000/svg', 'style'),\r\n paths = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n vertices = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n pathChildNodes = this.paths;\r\n\r\n // give the mask an id\r\n masks.setAttributeNS(null, 'id', 'text-mask');\r\n\r\n // create the css styles\r\n style.appendChild(document.createTextNode(`\r\n .element {\r\n font: ${this.opts.fontSizeLarge}pt Helvetica, Arial, sans-serif;\r\n alignment-baseline: 'middle';\r\n }\r\n .sub {\r\n font: ${this.opts.fontSizeSmall}pt Helvetica, Arial, sans-serif;\r\n }\r\n `));\r\n\r\n for (let path of pathChildNodes) {\r\n paths.appendChild(path);\r\n }\r\n for (let vertex of this.vertices) {\r\n vertices.appendChild(vertex);\r\n }\r\n for (let mask of this.maskElements) {\r\n masks.appendChild(mask);\r\n }\r\n for (let gradient of this.gradients) {\r\n defs.appendChild(gradient);\r\n }\r\n\r\n paths.setAttributeNS(null, 'mask', 'url(#text-mask)');\r\n\r\n if (this.svg) {\r\n this.svg.appendChild(defs);\r\n this.svg.appendChild(masks);\r\n this.svg.appendChild(style);\r\n this.svg.appendChild(paths);\r\n this.svg.appendChild(vertices);\r\n return this.svg;\r\n } else {\r\n let container = document.createElementNS('http://www.w3.org/2000/svg', 'g');\r\n container.appendChild(defs);\r\n container.appendChild(masks);\r\n container.appendChild(style);\r\n container.appendChild(paths);\r\n container.appendChild(vertices);\r\n return container;\r\n }\r\n }\r\n\r\n /**\r\n * Create a linear gradient to apply to a line\r\n *\r\n * @param {Line} line the line to apply the gradiation to.\r\n */\r\n createGradient(line) {\r\n // create the gradient and add it\r\n let gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient'),\r\n gradientUrl = `line-${this.gradientId++}`,\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n gradient.setAttributeNS(null, 'id', gradientUrl);\r\n gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\r\n gradient.setAttributeNS(null, 'x1', fromX);\r\n gradient.setAttributeNS(null, 'y1', fromY);\r\n gradient.setAttributeNS(null, 'x2', toX);\r\n gradient.setAttributeNS(null, 'y2', toY);\r\n\r\n let firstStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n firstStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getLeftElement()) || this.themeManager.getColor('C'));\r\n firstStop.setAttributeNS(null, 'offset', '20%');\r\n\r\n let secondStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n secondStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getRightElement() || this.themeManager.getColor('C')));\r\n secondStop.setAttributeNS(null, 'offset', '100%');\r\n\r\n gradient.appendChild(firstStop);\r\n gradient.appendChild(secondStop);\r\n\r\n this.gradients.push(gradient);\r\n\r\n return gradientUrl;\r\n }\r\n\r\n /**\r\n * Create a tspan element for sub or super scripts that styles the text\r\n * appropriately as one of those text types.\r\n *\r\n * @param {String} text the actual text\r\n * @param {String} shift the type of text, either 'sub', or 'super'\r\n */\r\n createSubSuperScripts(text, shift) {\r\n let elem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n elem.setAttributeNS(null, 'baseline-shift', shift);\r\n elem.appendChild(document.createTextNode(text));\r\n elem.setAttributeNS(null, 'class', 'sub');\r\n\r\n return elem;\r\n }\r\n\r\n /**\r\n * Determine drawing dimensiosn based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n determineDimensions(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n let padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n let scaleX = this.svg.clientWidth / this.drawingWidth;\r\n let scaleY = this.svg.clientHeight / this.drawingHeight;\r\n\r\n let scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n let viewBoxDim = Math.round(this.drawingWidth > this.drawingHeight ? this.drawingWidth : this.drawingHeight);\r\n\r\n this.svg.setAttributeNS(null, 'viewBox', `0 0 ${viewBoxDim} ${viewBoxDim}`);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.svg.clientHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.svg.clientWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Draw an svg ellipse as a ball.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n ball.setAttributeNS(null, 'cx', x + this.offsetX);\r\n ball.setAttributeNS(null, 'cy', y + this.offsetY);\r\n ball.setAttributeNS(null, 'r', this.opts.bondLength / 4.5);\r\n ball.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n\r\n this.vertices.push(ball);\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone(),\r\n normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral(),\r\n start,\r\n end;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n } else {\r\n start = l;\r\n end = r;\r\n }\r\n\r\n let dir = Vector2.subtract(end, start).normalize(),\r\n length = line.getLength(),\r\n step = 1.25 / (length / (this.opts.bondThickness * 3.0)),\r\n changed = false;\r\n\r\n let gradient = this.createGradient(line);\r\n\r\n for (let t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length),\r\n startDash = Vector2.add(start, to),\r\n width = 1.5 * t,\r\n dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n startDash.subtract(dashOffset);\r\n let endDash = startDash.clone();\r\n endDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n\r\n this.drawLine(new Line(startDash, endDash), null, gradient);\r\n }\r\n }\r\n\r\n /**\r\n * Draws a debug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + this.offsetX);\r\n point.setAttributeNS(null, 'cy', y + this.offsetY);\r\n point.setAttributeNS(null, 'r', '2');\r\n point.setAttributeNS(null, 'fill', '#f00');\r\n this.vertices.push(point);\r\n this.drawDebugText(x, y, debugText);\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\r\n textElem.setAttributeNS(null, 'x', x + this.offsetX);\r\n textElem.setAttributeNS(null, 'y', y + this.offsetY);\r\n textElem.setAttributeNS(null, 'class', 'debug');\r\n textElem.setAttributeNS(null, 'fill', '#ff0000');\r\n textElem.setAttributeNS(null, 'style', `\r\n font: 5px Droid Sans, sans-serif;\r\n `);\r\n textElem.appendChild(document.createTextNode(text));\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * Draws a line.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} dashed defaults to false.\r\n * @param {String} gradient gradient url. Defaults to null.\r\n */\r\n drawLine(line, dashed = false, gradient = null) {\r\n let opts = this.opts,\r\n stylesArr = [\r\n ['stroke-linecap', 'round'],\r\n ['stroke-dasharray', dashed ? '5, 5' : 'none'],\r\n ],\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n let styles = stylesArr.map(sub => sub.join(':')).join(';'),\r\n lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line');\r\n\r\n lineElem.setAttributeNS(null, 'x1', fromX);\r\n lineElem.setAttributeNS(null, 'y1', fromY);\r\n lineElem.setAttributeNS(null, 'x2', toX);\r\n lineElem.setAttributeNS(null, 'y2', toY);\r\n lineElem.setAttributeNS(null, 'style', styles);\r\n this.paths.push(lineElem);\r\n\r\n if (gradient == null) {\r\n gradient = this.createGradient(line, fromX, fromY, toX, toY);\r\n }\r\n lineElem.setAttributeNS(null, 'stroke', `url('#${gradient}')`);\r\n }\r\n\r\n /**\r\n * Draw a point.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // first create a mask\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', x + offsetX);\r\n mask.setAttributeNS(null, 'cy', y + offsetY);\r\n mask.setAttributeNS(null, 'r', '1.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // now create the point\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + offsetX);\r\n point.setAttributeNS(null, 'cy', y + offsetY);\r\n point.setAttributeNS(null, 'r', '0.75');\r\n point.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n this.vertices.push(point);\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n pos = {\r\n x: x + offsetX,\r\n y: y + offsetY,\r\n },\r\n textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text'),\r\n writingMode = 'horizontal-tb',\r\n letterSpacing = 'normal',\r\n textOrientation = 'mixed',\r\n textDirection = 'direction: ltr;',\r\n xShift = -2,\r\n yShift = 2.5;\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', pos.x);\r\n mask.setAttributeNS(null, 'cy', pos.y);\r\n mask.setAttributeNS(null, 'r', '3.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // determine writing mode\r\n if (/up|down/.test(direction) && !isTerminal) {\r\n writingMode = 'vertical-rl';\r\n textOrientation = 'upright';\r\n letterSpacing = '-1px';\r\n }\r\n\r\n if (direction === 'down' && !isTerminal) {\r\n xShift = 0;\r\n yShift = -2;\r\n } else if (direction === 'up' && !isTerminal) {\r\n xShift = 0.5;\r\n } else if (direction === 'left') {\r\n xShift = 2;\r\n }\r\n\r\n if (direction === 'left' || (direction === 'up' && !isTerminal)) {\r\n textDirection = 'direction: rtl; unicode-bidi: bidi-override;'\r\n }\r\n\r\n // now the text element\r\n textElem.setAttributeNS(null, 'x', pos.x + xShift);\r\n textElem.setAttributeNS(null, 'y', pos.y + yShift);\r\n textElem.setAttributeNS(null, 'class', 'element');\r\n textElem.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n textElem.setAttributeNS(null, 'style', `\r\n text-anchor: start;\r\n writing-mode: ${writingMode};\r\n text-orientation: ${textOrientation};\r\n letter-spacing: ${letterSpacing};\r\n ${textDirection}\r\n `);\r\n\r\n let textNode = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n // special case for element names that are 2 letters\r\n if (elementName.length > 1) {\r\n let textAnchor = /up|down/.test(direction) ? 'middle' : 'start';\r\n\r\n textNode.setAttributeNS(null, 'style', `\r\n unicode-bidi: plaintext;\r\n writing-mode: lr-tb;\r\n letter-spacing: normal;\r\n text-anchor: ${textAnchor};\r\n `);\r\n }\r\n textNode.appendChild(document.createTextNode(elementName));\r\n textElem.appendChild(textNode);\r\n\r\n // Charge\r\n if (charge) {\r\n let chargeElem = this.createSubSuperScripts(getChargeText(charge), 'super');\r\n textNode.appendChild(chargeElem);\r\n }\r\n\r\n let isotopeText = '0';\r\n\r\n if (isotope > 0) {\r\n let isotopeElem = this.createSubSuperScripts(isotope.toString(), 'super');\r\n textNode.appendChild(isotopeElem);\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') &&\r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = {\r\n '0O': {\r\n element: 'O',\r\n count: 2,\r\n hydrogenCount: 0,\r\n previousElement: 'C',\r\n charge: ''\r\n }\r\n }\r\n charge = 0;\r\n }\r\n\r\n if (hydrogens > 0) {\r\n let hydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n hydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n hydrogenElem.appendChild(document.createTextNode('H'));\r\n textElem.appendChild(hydrogenElem);\r\n\r\n if (hydrogens > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogens, 'sub');\r\n hydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let element = attachedPseudoElement[key].element,\r\n elementCount = attachedPseudoElement[key].count,\r\n hydrogenCount = attachedPseudoElement[key].hydrogenCount,\r\n elementCharge = attachedPseudoElement[key].charge,\r\n pseudoElementElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoElementElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoElementElem.appendChild(document.createTextNode(element));\r\n pseudoElementElem.setAttributeNS(null, 'fill', this.themeManager.getColor(element));\r\n\r\n if (elementCharge !== 0) {\r\n let elementChargeElem = this.createSubSuperScripts(getChargeText(elementCharge), 'super');\r\n pseudoElementElem.appendChild(elementChargeElem);\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n let pseudoHydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoHydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoHydrogenElem.appendChild(document.createTextNode('H'));\r\n pseudoElementElem.appendChild(pseudoHydrogenElem);\r\n\r\n if (hydrogenCount > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogenCount, 'sub');\r\n pseudoHydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n if (elementCount > 1) {\r\n let elementCountElem = this.createSubSuperScripts(elementCount, 'sub');\r\n pseudoElementElem.appendChild(elementCountElem);\r\n }\r\n\r\n textElem.appendChild(pseudoElementElem);\r\n }\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * @param {Line} line the line object to create the wedge from\r\n */\r\n drawWedge(line) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l,\r\n end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness)),\r\n u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness)),\r\n v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness)),\r\n w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n let polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'),\r\n gradient = this.createGradient(line, l.x, l.y, r.x, r.y);\r\n polygon.setAttributeNS(null, 'points', `${t.x},${t.y} ${u.x},${u.y} ${v.x},${v.y} ${w.x},${w.y}`);\r\n polygon.setAttributeNS(null, 'fill', `url('#${gradient}')`);\r\n this.paths.push(polygon);\r\n }\r\n}\r\n\r\nmodule.exports = SvgWrapper;","class ThemeManager {\r\n constructor(colors, theme) {\r\n this.colors = colors;\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n if (key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.theme) {\r\n return this.theme[key];\r\n }\r\n }\r\n\r\n return this.theme['C'];\r\n }\r\n\r\n /**\r\n * Sets the theme to the specified string if it exists. If it does not, this\r\n * does nothing.\r\n *\r\n * @param {String} theme the name of the theme to switch to\r\n */\r\n setTheme(theme) {\r\n if (this.colors.hasOwnProperty(theme)) {\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n // TODO: this probably should notify those who are watching this theme\r\n // manager that the theme has changed so that colors can be changed\r\n // on the fly\r\n }\r\n}\r\n\r\nmodule.exports = ThemeManager;","/**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\nfunction getChargeText(charge) {\r\n console.log('in the utility version of getChargeText');\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n getChargeText,\r\n}","//@ts-check\r\n\r\n/** \r\n * A class representing a 2D vector.\r\n * \r\n * @property {Number} x The x component of the vector.\r\n * @property {Number} y The y component of the vector.\r\n */\r\nclass Vector2 {\r\n /**\r\n * The constructor of the class Vector2.\r\n *\r\n * @param {(Number|Vector2)} x The initial x coordinate value or, if the single argument, a Vector2 object.\r\n * @param {Number} y The initial y coordinate value.\r\n */\r\n constructor(x, y) {\r\n if (arguments.length == 0) {\r\n this.x = 0;\r\n this.y = 0;\r\n } else if (arguments.length == 1) {\r\n this.x = x.x;\r\n this.y = x.y;\r\n } else {\r\n this.x = x;\r\n this.y = y;\r\n }\r\n }\r\n\r\n /**\r\n * Clones this vector and returns the clone.\r\n *\r\n * @returns {Vector2} The clone of this vector.\r\n */\r\n clone() {\r\n return new Vector2(this.x, this.y);\r\n }\r\n\r\n /**\r\n * Returns a string representation of this vector.\r\n *\r\n * @returns {String} A string representation of this vector.\r\n */\r\n toString() {\r\n return '(' + this.x + ',' + this.y + ')';\r\n }\r\n\r\n /**\r\n * Add the x and y coordinate values of a vector to the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n add(vec) {\r\n this.x += vec.x;\r\n this.y += vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Subtract the x and y coordinate values of a vector from the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n subtract(vec) {\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Divide the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n divide(scalar) {\r\n this.x /= scalar;\r\n this.y /= scalar;\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Multiply the x and y coordinate values of this vector by the values of another vector.\r\n *\r\n * @param {Vector2} v A vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiply(v) {\r\n this.x *= v.x;\r\n this.y *= v.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Multiply the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiplyScalar(scalar) {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Inverts this vector. Same as multiply(-1.0).\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n invert() {\r\n this.x = -this.x;\r\n this.y = -this.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vector in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n angle() {\r\n return Math.atan2(this.y, this.x);\r\n }\r\n\r\n /**\r\n * Returns the euclidean distance between this vector and another vector.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Number} The euclidean distance between the two vectors.\r\n */\r\n distance(vec) {\r\n return Math.sqrt((vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y));\r\n }\r\n\r\n /**\r\n * Returns the squared euclidean distance between this vector and another vector. When only the relative distances of a set of vectors are needed, this is is less expensive than using distance(vec).\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} The squared euclidean distance of the two vectors.\r\n */\r\n distanceSq(vec) {\r\n return (vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to the coordinate system.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to the coordinate system.\r\n */\r\n clockwise(vec) {\r\n let a = this.y * vec.x;\r\n let b = this.x * vec.y;\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to an arbitrary third vector.\r\n *\r\n * @param {Vector2} center The central vector.\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to an arbitrary third vector.\r\n */\r\n relativeClockwise(center, vec) {\r\n let a = (this.y - center.y) * (vec.x - center.x);\r\n let b = (this.x - center.x) * (vec.y - center.y);\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Rotates this vector by a given number of radians around the origin of the coordinate system.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotate(angle) {\r\n let tmp = new Vector2(0, 0);\r\n let cosAngle = Math.cos(angle);\r\n let sinAngle = Math.sin(angle);\r\n\r\n tmp.x = this.x * cosAngle - this.y * sinAngle;\r\n tmp.y = this.x * sinAngle + this.y * cosAngle;\r\n \r\n this.x = tmp.x;\r\n this.y = tmp.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this vector around another vector.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @param {Vector2} vec The vector which is used as the rotational center.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateAround(angle, vec) {\r\n let s = Math.sin(angle);\r\n let c = Math.cos(angle);\r\n\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n let x = this.x * c - this.y * s;\r\n let y = this.x * s + this.y * c;\r\n\r\n this.x = x + vec.x;\r\n this.y = y + vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate a vector around a given center to the same angle as another vector (so that the two vectors and the center are in a line, with both vectors on one side of the center), keeps the distance from this vector to the center.\r\n *\r\n * @param {Vector2} vec The vector to rotate this vector to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} [offsetAngle=0.0] An additional amount of radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateTo(vec, center, offsetAngle = 0.0) {\r\n // Problem if this is first position\r\n this.x += 0.001;\r\n this.y -= 0.001;\r\n\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n\r\n this.rotateAround(angle + offsetAngle, center);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates the vector away from a specified vector around a center.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n */\r\n rotateAwayFrom(vec, center, angle) {\r\n this.rotateAround(angle, center);\r\n \r\n let distSqA = this.distanceSq(vec);\r\n \r\n this.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = this.distanceSq(vec);\r\n\r\n // If it was rotated towards the other vertex, rotate in other direction by same amount.\r\n if (distSqB < distSqA) {\r\n this.rotateAround(2.0 * angle, center);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector away from a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateAwayFromAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB < distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector towards a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated towards to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateTowardsAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB > distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the angles between this vector and another vector around a common center of rotation.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @param {Vector2} center The center of rotation.\r\n * @returns {Number} The angle between this vector and another vector around a center of rotation in radians.\r\n */\r\n getRotateToAngle(vec, center) {\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n \r\n return Number.isNaN(angle) ? 0.0 : angle;\r\n }\r\n\r\n /**\r\n * Checks whether a vector lies within a polygon spanned by a set of vectors.\r\n *\r\n * @param {Vector2[]} polygon An array of vectors spanning the polygon.\r\n * @returns {Boolean} A boolean indicating whether or not this vector is within a polygon.\r\n */\r\n isInPolygon(polygon) {\r\n let inside = false;\r\n\r\n // Its not always a given, that the polygon is convex (-> sugars)\r\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\r\n if (((polygon[i].y > this.y) != (polygon[j].y > this.y)) &&\r\n (this.x < (polygon[j].x - polygon[i].x) * (this.y - polygon[i].y) /\r\n (polygon[j].y - polygon[i].y) + polygon[i].x)) {\r\n inside = !inside;\r\n }\r\n }\r\n\r\n\r\n return inside;\r\n }\r\n\r\n /**\r\n * Returns the length of this vector.\r\n *\r\n * @returns {Number} The length of this vector.\r\n */\r\n length() {\r\n return Math.sqrt((this.x * this.x) + (this.y * this.y));\r\n }\r\n\r\n /**\r\n * Returns the square of the length of this vector.\r\n *\r\n * @returns {Number} The square of the length of this vector.\r\n */\r\n lengthSq() {\r\n return (this.x * this.x) + (this.y * this.y);\r\n }\r\n\r\n /**\r\n * Normalizes this vector.\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n normalize() {\r\n this.divide(this.length());\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns a normalized copy of this vector.\r\n *\r\n * @returns {Vector2} A normalized copy of this vector.\r\n */\r\n normalized() {\r\n return Vector2.divideScalar(this, this.length());\r\n }\r\n\r\n /**\r\n * Calculates which side of a line spanned by two vectors this vector is.\r\n *\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} A number indicating the side of this vector, given a line spanned by two other vectors.\r\n */\r\n whichSide(vecA, vecB) {\r\n return (this.x - vecA.x) * (vecB.y - vecA.y) - (this.y - vecA.y) * (vecB.x - vecA.x);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is on the same side of a line spanned by two vectors as another vector.\r\n *\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @param {Vector2} vecC A vector to check whether or not it is on the same side as this vector.\r\n * @returns {Boolean} Returns a boolean indicating whether or not this vector is on the same side as another vector.\r\n */\r\n sameSideAs(vecA, vecB, vecC) {\r\n let d = this.whichSide(vecA, vecB);\r\n let dRef = vecC.whichSide(vecA, vecB);\r\n\r\n return d < 0 && dRef < 0 || d == 0 && dRef == 0 || d > 0 && dRef > 0;\r\n }\r\n\r\n /**\r\n * Adds two vectors and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A summand.\r\n * @param {Vector2} vecB A summand.\r\n * @returns {Vector2} Returns the sum of two vectors.\r\n */\r\n static add(vecA, vecB) {\r\n return new Vector2(vecA.x + vecB.x, vecA.y + vecB.y);\r\n }\r\n\r\n /**\r\n * Subtracts one vector from another and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The minuend.\r\n * @param {Vector2} vecB The subtrahend.\r\n * @returns {Vector2} Returns the difference of two vectors.\r\n */\r\n static subtract(vecA, vecB) {\r\n return new Vector2(vecA.x - vecB.x, vecA.y - vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiply(vecA, vecB) {\r\n return new Vector2(vecA.x * vecB.x, vecA.y * vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vec A vector.\r\n * @param {Number} scalar A scalar.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiplyScalar(vec, scalar) {\r\n return new Vector2(vec.x, vec.y).multiplyScalar(scalar);\r\n }\r\n\r\n /**\r\n * Returns the midpoint of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2} The midpoint of the line spanned by two vectors.\r\n */\r\n static midpoint(vecA, vecB) {\r\n return new Vector2((vecA.x + vecB.x) / 2, (vecA.y + vecB.y) / 2);\r\n }\r\n\r\n /**\r\n * Returns the normals of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two normals, each represented by a vector.\r\n */\r\n static normals(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n new Vector2(-delta.y, delta.x),\r\n new Vector2(delta.y, -delta.x)\r\n ];\r\n }\r\n\r\n /**\r\n * Returns the unit (normalized normal) vectors of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two unit vectors.\r\n */\r\n static units(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n (new Vector2(-delta.y, delta.x)).normalize(),\r\n (new Vector2(delta.y, -delta.x)).normalize()\r\n ];\r\n }\r\n\r\n /**\r\n * Divides a vector by another vector and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Vector2} vecB The divisor.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divide(vecA, vecB) {\r\n return new Vector2(vecA.x / vecB.x, vecA.y / vecB.y);\r\n }\r\n\r\n /**\r\n * Divides a vector by a scalar and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Number} s The scalar.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divideScalar(vecA, s) {\r\n return new Vector2(vecA.x / s, vecA.y / s);\r\n }\r\n\r\n /**\r\n * Returns the dot product of two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The dot product of two vectors.\r\n */\r\n static dot(vecA, vecB) {\r\n return vecA.x * vecB.x + vecA.y * vecB.y;\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The angle between two vectors in radians.\r\n */\r\n static angle(vecA, vecB) {\r\n let dot = Vector2.dot(vecA, vecB);\r\n\r\n return Math.acos(dot / (vecA.length() * vecB.length()));\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors based on a third vector in between.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A (central) vector.\r\n * @param {Vector2} vecC A vector.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static threePointangle(vecA, vecB, vecC) {\r\n let ab = Vector2.subtract(vecB, vecA);\r\n let bc = Vector2.subtract(vecC, vecB);\r\n let abLength = vecA.distance(vecB);\r\n let bcLength = vecB.distance(vecC);\r\n\r\n return Math.acos(Vector2.dot(ab, bc) / (abLength * bcLength));\r\n }\r\n \r\n /**\r\n * Returns the scalar projection of a vector on another vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The vector to be projected.\r\n * @param {Vector2} vecB The vector to be projection upon.\r\n * @returns {Number} The scalar component.\r\n */\r\n static scalarProjection(vecA, vecB) {\r\n let unit = vecB.normalized();\r\n \r\n return Vector2.dot(vecA, unit);\r\n }\r\n\r\n /**\r\n * Returns the average vector (normalized) of the input vectors.\r\n *\r\n * @static\r\n * @param {Array} vecs An array containing vectors.\r\n * @returns {Vector2} The resulting vector (normalized).\r\n */\r\n static averageDirection(vecs) {\r\n let avg = new Vector2(0.0, 0.0);\r\n\r\n for (var i = 0; i < vecs.length; i++) {\r\n let vec = vecs[i];\r\n avg.add(vec);\r\n }\r\n\r\n return avg.normalize();\r\n }\r\n}\r\n\r\nmodule.exports = Vector2;","//@ts-check\r\nconst MathHelper = require('./MathHelper')\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Atom = require('./Atom')\r\nconst VertexState = require('./VertexState')\r\n\r\n/** \r\n * A class representing a vertex.\r\n * \r\n * @property {Number} id The id of this vertex.\r\n * @property {Atom} value The atom associated with this vertex.\r\n * @property {Vector2} position The position of this vertex.\r\n * @property {Vector2} previousPosition The position of the previous vertex.\r\n * @property {Number|null} parentVertexId The id of the previous vertex.\r\n * @property {Number[]} children The ids of the children of this vertex.\r\n * @property {Number[]} spanningTreeChildren The ids of the children of this vertex as defined in the spanning tree defined by the SMILES.\r\n * @property {Number[]} edges The ids of edges associated with this vertex.\r\n * @property {Boolean} positioned A boolean indicating whether or not this vertex has been positioned.\r\n * @property {Number} angle The angle of this vertex.\r\n * @property {Number} dir The direction of this vertex.\r\n * @property {Number} neighbourCount The number of neighbouring vertices.\r\n * @property {Number[]} neighbours The vertex ids of neighbouring vertices.\r\n * @property {String[]} neighbouringElements The element symbols associated with neighbouring vertices.\r\n * @property {Boolean} forcePositioned A boolean indicating whether or not this vertex was positioned using a force-based approach.\r\n * @property {Number} vertexState enum of VertexState for DFS.\r\n */\r\n\r\nclass Vertex {\r\n /**\r\n * The constructor for the class Vertex.\r\n *\r\n * @param {Atom} value The value associated with this vertex.\r\n * @param {Number} [x=0] The initial x coordinate of the positional vector of this vertex.\r\n * @param {Number} [y=0] The initial y coordinate of the positional vector of this vertex.\r\n */\r\n constructor(value, x = 0, y = 0) {\r\n this.id = null;\r\n this.value = value;\r\n this.position = new Vector2(x ? x : 0, y ? y : 0);\r\n this.previousPosition = new Vector2(0, 0);\r\n this.parentVertexId = null;\r\n this.children = Array();\r\n this.spanningTreeChildren = Array();\r\n this.edges = Array();\r\n this.positioned = false;\r\n this.angle = null;\r\n this.dir = 1.0;\r\n this.neighbourCount = 0;\r\n this.neighbours = Array();\r\n this.neighbouringElements = Array();\r\n this.forcePositioned = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n this.component = -1;\r\n this.digits = [];\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex.\r\n * \r\n * @param {Number} x The x component of the coordinates.\r\n * @param {Number} y The y component of the coordinates.\r\n * \r\n */\r\n setPosition(x, y) {\r\n this.position.x = x;\r\n this.position.y = y;\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex from a Vector2.\r\n * \r\n * @param {Vector2} v A 2D vector.\r\n * \r\n */\r\n setPositionFromVector(v) {\r\n this.position.x = v.x;\r\n this.position.y = v.y;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n */\r\n addChild(vertexId) {\r\n this.children.push(vertexId);\r\n this.neighbours.push(vertexId);\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex as the second child of the neighbours array,\r\n * except this vertex is the first vertex of the SMILE string, then it is added as the first.\r\n * This is used to get the correct ordering of neighbours for parity calculations.\r\n * If a hydrogen is implicitly attached to the chiral center, insert as the third child.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n * @param {Number} ringbondIndex The index of the ringbond.\r\n */\r\n addRingbondChild(vertexId, ringbondIndex) {\r\n this.children.push(vertexId);\r\n\r\n if (this.value.bracket) {\r\n let index = 1;\r\n\r\n if (this.id === 0 && this.value.bracket.hcount === 0) {\r\n index = 0;\r\n }\r\n \r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 0) {\r\n index = 2;\r\n }\r\n\r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 2;\r\n } else {\r\n index = 3;\r\n }\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 0) {\r\n index = 1;\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 1;\r\n } else {\r\n index = 2;\r\n }\r\n }\r\n \r\n this.neighbours.splice(index, 0, vertexId);\r\n } else {\r\n this.neighbours.push(vertexId);\r\n }\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Set the vertex id of the parent.\r\n * \r\n * @param {Number} parentVertexId The parents vertex id.\r\n */\r\n setParentVertexId(parentVertexId) {\r\n this.neighbourCount++;\r\n this.parentVertexId = parentVertexId;\r\n this.neighbours.push(parentVertexId);\r\n }\r\n\r\n /**\r\n * Returns true if this vertex is terminal (has no parent or child vertices), otherwise returns false. Always returns true if associated value has property hasAttachedPseudoElements set to true.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not this vertex is terminal.\r\n */\r\n isTerminal() {\r\n if (this.value.hasAttachedPseudoElements) {\r\n return true;\r\n }\r\n\r\n return (this.parentVertexId === null && this.children.length < 2) || this.children.length === 0;\r\n }\r\n\r\n /**\r\n * Clones this vertex and returns the clone.\r\n *\r\n * @returns {Vertex} A clone of this vertex.\r\n */\r\n clone() {\r\n let clone = new Vertex(this.value, this.position.x, this.position.y);\r\n clone.id = this.id;\r\n clone.previousPosition = new Vector2(this.previousPosition.x, this.previousPosition.y);\r\n clone.parentVertexId = this.parentVertexId;\r\n clone.children = ArrayHelper.clone(this.children);\r\n clone.spanningTreeChildren = ArrayHelper.clone(this.spanningTreeChildren);\r\n clone.edges = ArrayHelper.clone(this.edges);\r\n clone.positioned = this.positioned;\r\n clone.angle = this.angle;\r\n clone.forcePositioned = this.forcePositioned;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns true if this vertex and the supplied vertex both have the same id, else returns false.\r\n *\r\n * @param {Vertex} vertex The vertex to check.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices have the same id.\r\n */\r\n equals(vertex) {\r\n return this.id === vertex.id;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vertexes positional vector. If a reference vector is supplied in relations to this vector, else in relations to the coordinate system.\r\n *\r\n * @param {Vector2} [referenceVector=null] - The reference vector.\r\n * @param {Boolean} [returnAsDegrees=false] - If true, returns angle in degrees, else in radians.\r\n * @returns {Number} The angle of this vertex.\r\n */\r\n getAngle(referenceVector = null, returnAsDegrees = false) {\r\n let u = null;\r\n\r\n if (!referenceVector) {\r\n u = Vector2.subtract(this.position, this.previousPosition);\r\n } else {\r\n u = Vector2.subtract(this.position, referenceVector);\r\n }\r\n\r\n if (returnAsDegrees) {\r\n return MathHelper.toDeg(u.angle());\r\n }\r\n\r\n return u.angle();\r\n }\r\n\r\n /**\r\n * Returns the suggested text direction when text is added at the position of this vertex.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @returns {String} The suggested direction of the text.\r\n */\r\n getTextDirection(vertices) {\r\n let neighbours = this.getDrawnNeighbours(vertices);\r\n let angles = Array();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n angles.push(this.getAngle(vertices[neighbours[i]].position));\r\n }\r\n\r\n let textAngle = MathHelper.meanAngle(angles);\r\n\r\n // Round to 0, 90, 180 or 270 degree\r\n let halfPi = Math.PI / 2.0;\r\n textAngle = Math.round(Math.round(textAngle / halfPi) * halfPi);\r\n\r\n if (textAngle === 2) {\r\n return 'down';\r\n } else if (textAngle === -2) {\r\n return 'up';\r\n } else if (textAngle === 0 || textAngle === -0) {\r\n return 'right'; // is checking for -0 necessary?\r\n } else if (textAngle === 3 || textAngle === -3) {\r\n return 'left';\r\n } else {\r\n return 'down'; // default to down\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices.\r\n *\r\n * @param {Number} [vertexId=null] If a value is supplied, the vertex with this id is excluded from the returned indices.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices.\r\n */\r\n getNeighbours(vertexId = null) {\r\n if (vertexId === null) {\r\n return this.neighbours.slice();\r\n }\r\n\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (this.neighbours[i] !== vertexId) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices that will be drawn (vertex.value.isDrawn === true).\r\n * \r\n * @param {Vertex[]} vertices An array containing the vertices associated with the current molecule.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices that will be drawn.\r\n */\r\n getDrawnNeighbours(vertices) {\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (vertices[this.neighbours[i]].value.isDrawn) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns the number of neighbours of this vertex.\r\n *\r\n * @returns {Number} The number of neighbours.\r\n */\r\n getNeighbourCount() {\r\n return this.neighbourCount;\r\n }\r\n\r\n /**\r\n * Returns a list of ids of vertices neighbouring this one in the original spanning tree, excluding the ringbond connections.\r\n *\r\n * @param {Number} [vertexId=null] If supplied, the vertex with this id is excluded from the array returned.\r\n * @returns {Number[]} An array containing the ids of the neighbouring vertices.\r\n */\r\n getSpanningTreeNeighbours(vertexId = null) {\r\n let neighbours = Array();\r\n\r\n for (let i = 0; i < this.spanningTreeChildren.length; i++) {\r\n if (vertexId === undefined || vertexId != this.spanningTreeChildren[i]) {\r\n neighbours.push(this.spanningTreeChildren[i]);\r\n }\r\n }\r\n\r\n if (this.parentVertexId != null) {\r\n if (vertexId === undefined || vertexId != this.parentVertexId) {\r\n neighbours.push(this.parentVertexId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Gets the next vertex in the ring in opposide direction to the supplied vertex id.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @param {Number} ringId The id of the ring containing this vertex.\r\n * @param {Number} previousVertexId The id of the previous vertex. The next vertex will be opposite from the vertex with this id as seen from this vertex.\r\n * @returns {Number} The id of the next vertex in the ring.\r\n */\r\n getNextInRing(vertices, ringId, previousVertexId) {\r\n let neighbours = this.getNeighbours();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (ArrayHelper.contains(vertices[neighbours[i]].value.rings, {\r\n value: ringId\r\n }) &&\r\n neighbours[i] != previousVertexId) {\r\n return neighbours[i];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n\r\nmodule.exports = Vertex;","//@ts-check\r\n\r\nclass VertexState {\r\n\r\n /**\r\n * Enum values of Vertex State for DFS\r\n * @return {{NOT_FOUND: number, OPEN: number, CLOSED: number, FULLY_CLOSED: number}}\r\n */\r\n static get VALUES() {\r\n return { NOT_FOUND: 0, OPEN: 1, CLOSED: 2, FULLY_CLOSED: 3 };\r\n }\r\n}\r\n\r\nmodule.exports = VertexState;\r\n"]} \ No newline at end of file diff --git a/doc/ArrayHelper.html b/doc/ArrayHelper.html index 5e7fc03c..c1dd67d1 100644 --- a/doc/ArrayHelper.html +++ b/doc/ArrayHelper.html @@ -3398,7 +3398,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/ArrayHelper.js.html b/doc/ArrayHelper.js.html index 60ca0c38..a4842723 100644 --- a/doc/ArrayHelper.js.html +++ b/doc/ArrayHelper.js.html @@ -438,7 +438,7 @@

ArrayHelper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Atom.html b/doc/Atom.html index 2cf4a1d1..dc036b97 100644 --- a/doc/Atom.html +++ b/doc/Atom.html @@ -2906,7 +2906,7 @@

restoreRi
- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Atom.js.html b/doc/Atom.js.html index 5345e305..09c75409 100644 --- a/doc/Atom.js.html +++ b/doc/Atom.js.html @@ -594,7 +594,7 @@

Atom.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/CanvasWrapper.html b/doc/CanvasWrapper.html index 857ace89..deff0913 100644 --- a/doc/CanvasWrapper.html +++ b/doc/CanvasWrapper.html @@ -3783,7 +3783,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/CanvasWrapper.js.html b/doc/CanvasWrapper.js.html index 55edb01c..a3b175a1 100644 --- a/doc/CanvasWrapper.js.html +++ b/doc/CanvasWrapper.js.html @@ -948,7 +948,7 @@

CanvasWrapper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/DecayPoint.js.html b/doc/DecayPoint.js.html index 122af659..e6682524 100644 --- a/doc/DecayPoint.js.html +++ b/doc/DecayPoint.js.html @@ -73,7 +73,7 @@

DecayPoint.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Drawer.html b/doc/Drawer.html index a0fe4b0f..183c8e64 100644 --- a/doc/Drawer.html +++ b/doc/Drawer.html @@ -10857,7 +10857,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Drawer.js.html b/doc/Drawer.js.html index 05dc5338..4084e00e 100644 --- a/doc/Drawer.js.html +++ b/doc/Drawer.js.html @@ -3218,7 +3218,7 @@

Drawer.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Edge.html b/doc/Edge.html index 956165e6..55622838 100644 --- a/doc/Edge.html +++ b/doc/Edge.html @@ -1113,7 +1113,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Edge.js.html b/doc/Edge.js.html index 9f3bfbc0..d4e2b4cc 100644 --- a/doc/Edge.js.html +++ b/doc/Edge.js.html @@ -134,7 +134,7 @@

Edge.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Graph.html b/doc/Graph.html index a5149e6d..8688ffef 100644 --- a/doc/Graph.html +++ b/doc/Graph.html @@ -8816,7 +8816,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Graph.js.html b/doc/Graph.js.html index be246cd4..e171ac3d 100644 --- a/doc/Graph.js.html +++ b/doc/Graph.js.html @@ -1892,7 +1892,7 @@

Graph.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Line.html b/doc/Line.html index cffb32eb..05333cd4 100644 --- a/doc/Line.html +++ b/doc/Line.html @@ -3056,7 +3056,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Line.js.html b/doc/Line.js.html index 664dce78..f77ae196 100644 --- a/doc/Line.js.html +++ b/doc/Line.js.html @@ -358,7 +358,7 @@

Line.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MathHelper.html b/doc/MathHelper.html index a7498686..988590fc 100644 --- a/doc/MathHelper.html +++ b/doc/MathHelper.html @@ -1869,7 +1869,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MathHelper.js.html b/doc/MathHelper.js.html index e1be9474..e42406de 100644 --- a/doc/MathHelper.js.html +++ b/doc/MathHelper.js.html @@ -214,7 +214,7 @@

MathHelper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableBoolean.html b/doc/MutableBoolean.html index 2118a8dc..3b0bf2e8 100644 --- a/doc/MutableBoolean.html +++ b/doc/MutableBoolean.html @@ -275,7 +275,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableBoolean.js.html b/doc/MutableBoolean.js.html index 572ab46e..49d6ca28 100644 --- a/doc/MutableBoolean.js.html +++ b/doc/MutableBoolean.js.html @@ -79,7 +79,7 @@

MutableBoolean.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableCounter.html b/doc/MutableCounter.html index 130c62f5..0d539ad8 100644 --- a/doc/MutableCounter.html +++ b/doc/MutableCounter.html @@ -223,7 +223,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableCounter.js.html b/doc/MutableCounter.js.html index 5d5f4ed1..7c7dd0e9 100644 --- a/doc/MutableCounter.js.html +++ b/doc/MutableCounter.js.html @@ -80,7 +80,7 @@

MutableCounter.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Ring.html b/doc/Ring.html index 56a85c58..7c6948af 100644 --- a/doc/Ring.html +++ b/doc/Ring.html @@ -1908,7 +1908,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Ring.js.html b/doc/Ring.js.html index cfccfc3a..f644525d 100644 --- a/doc/Ring.js.html +++ b/doc/Ring.js.html @@ -267,7 +267,7 @@

Ring.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/RingConnection.html b/doc/RingConnection.html index 2da9f6e5..2986f307 100644 --- a/doc/RingConnection.html +++ b/doc/RingConnection.html @@ -1602,7 +1602,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/RingConnection.js.html b/doc/RingConnection.js.html index 8bfc1d10..5f082165 100644 --- a/doc/RingConnection.js.html +++ b/doc/RingConnection.js.html @@ -216,7 +216,7 @@

RingConnection.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SSSR.html b/doc/SSSR.html index c4abf4aa..ec6ef75a 100644 --- a/doc/SSSR.html +++ b/doc/SSSR.html @@ -2524,7 +2524,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SSSR.js.html b/doc/SSSR.js.html index d32c8958..29c93c63 100644 --- a/doc/SSSR.js.html +++ b/doc/SSSR.js.html @@ -626,7 +626,7 @@

SSSR.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SvgDrawer.js.html b/doc/SvgDrawer.js.html index bfd58b91..1412ae78 100644 --- a/doc/SvgDrawer.js.html +++ b/doc/SvgDrawer.js.html @@ -394,7 +394,7 @@

SvgDrawer.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SvgWrapper.js.html b/doc/SvgWrapper.js.html index 7bf77ebe..6890e62b 100644 --- a/doc/SvgWrapper.js.html +++ b/doc/SvgWrapper.js.html @@ -659,7 +659,7 @@

SvgWrapper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/ThemeManager.js.html b/doc/ThemeManager.js.html index 93d6110d..c324dde7 100644 --- a/doc/ThemeManager.js.html +++ b/doc/ThemeManager.js.html @@ -97,7 +97,7 @@

ThemeManager.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/UtilityFunctions.js.html b/doc/UtilityFunctions.js.html index a1ee666b..46322931 100644 --- a/doc/UtilityFunctions.js.html +++ b/doc/UtilityFunctions.js.html @@ -78,7 +78,7 @@

UtilityFunctions.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vector2.html b/doc/Vector2.html index 729147ff..ce705f26 100644 --- a/doc/Vector2.html +++ b/doc/Vector2.html @@ -7088,7 +7088,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vector2.js.html b/doc/Vector2.js.html index c8b45bd3..7a6a5859 100644 --- a/doc/Vector2.js.html +++ b/doc/Vector2.js.html @@ -684,7 +684,7 @@

Vector2.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vertex.html b/doc/Vertex.html index b0e86d44..e25ff58f 100644 --- a/doc/Vertex.html +++ b/doc/Vertex.html @@ -3036,7 +3036,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:35 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vertex.js.html b/doc/Vertex.js.html index 7dabd448..e141dbf2 100644 --- a/doc/Vertex.js.html +++ b/doc/Vertex.js.html @@ -403,7 +403,7 @@

Vertex.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/VertexState.js.html b/doc/VertexState.js.html index e967f356..69ff185a 100644 --- a/doc/VertexState.js.html +++ b/doc/VertexState.js.html @@ -70,7 +70,7 @@

VertexState.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/global.html b/doc/global.html index 34fd961e..5a0dd570 100644 --- a/doc/global.html +++ b/doc/global.html @@ -297,7 +297,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/index.html b/doc/index.html index a2f6c831..ebc85c24 100644 --- a/doc/index.html +++ b/doc/index.html @@ -381,7 +381,7 @@

Contributors


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:47:34 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme.
From 23ccce217742896a618b9e2f50e74c9f7d85cd45 Mon Sep 17 00:00:00 2001 From: privrja Date: Fri, 23 Apr 2021 10:39:09 +0200 Subject: [PATCH 3/6] Cyclic of 2 blocks --- dist/smiles-drawer.js | 8 +++++++- dist/smiles-drawer.min.js | 2 +- dist/smiles-drawer.min.js.map | 2 +- doc/ArrayHelper.html | 2 +- doc/ArrayHelper.js.html | 2 +- doc/Atom.html | 2 +- doc/Atom.js.html | 2 +- doc/CanvasWrapper.html | 2 +- doc/CanvasWrapper.js.html | 2 +- doc/DecayPoint.js.html | 2 +- doc/Drawer.html | 2 +- doc/Drawer.js.html | 2 +- doc/Edge.html | 2 +- doc/Edge.js.html | 2 +- doc/Graph.html | 38 +++++++++++++++++------------------ doc/Graph.js.html | 4 +--- doc/Line.html | 2 +- doc/Line.js.html | 2 +- doc/MathHelper.html | 2 +- doc/MathHelper.js.html | 2 +- doc/MutableBoolean.html | 2 +- doc/MutableBoolean.js.html | 2 +- doc/MutableCounter.html | 2 +- doc/MutableCounter.js.html | 2 +- doc/Ring.html | 2 +- doc/Ring.js.html | 2 +- doc/RingConnection.html | 2 +- doc/RingConnection.js.html | 2 +- doc/SSSR.html | 2 +- doc/SSSR.js.html | 2 +- doc/SvgDrawer.js.html | 2 +- doc/SvgWrapper.js.html | 2 +- doc/ThemeManager.js.html | 2 +- doc/UtilityFunctions.js.html | 2 +- doc/Vector2.html | 2 +- doc/Vector2.js.html | 2 +- doc/Vertex.html | 2 +- doc/Vertex.js.html | 2 +- doc/VertexState.js.html | 2 +- doc/global.html | 2 +- doc/index.html | 2 +- spec/blocksSpec.js | 17 ++++++++++++++++ src/Graph.js | 2 -- src/SmallGraph.js | 7 ++++++- 44 files changed, 88 insertions(+), 64 deletions(-) diff --git a/dist/smiles-drawer.js b/dist/smiles-drawer.js index ec07e9de..15a1f12e 100644 --- a/dist/smiles-drawer.js +++ b/dist/smiles-drawer.js @@ -10800,7 +10800,13 @@ class SmallGraph { this.dfsInitialization(); this.isCyclic = false; - this.dfsCyclic(this._nodes[0], -1); + + if (this._nodes.length === 2 && this._nodes[0].neighbours.length === 2 && this._nodes[1].neighbours.length === 2) { + this.isCyclic = true; + this._nodeOnRing = this._nodes[0]; + } else { + this.dfsCyclic(this._nodes[0], -1); + } } dfsCyclic(vertex, vertexFromId) { diff --git a/dist/smiles-drawer.min.js b/dist/smiles-drawer.min.js index 0f55596a..44d830fe 100644 --- a/dist/smiles-drawer.min.js +++ b/dist/smiles-drawer.min.js @@ -1,4 +1,4 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i{const context=canvas.getContext("2d");context.clearRect(0,0,canvas.width,canvas.height)})},SmilesDrawer.parse=function(smiles,successCallback,errorCallback){try{successCallback&&successCallback(Parser.parse(smiles))}catch(err){errorCallback&&errorCallback(err)}},canUseDOM&&(window.SmilesDrawer=SmilesDrawer),Array.prototype.fill||Object.defineProperty(Array.prototype,"fill",{value:function(value){if(null==this)throw new TypeError("this is null or not defined");for(var O=Object(this),len=O.length>>>0,start=arguments[1],relativeStart=start>>0,k=0>relativeStart?_Mathmax(len+relativeStart,0):_Mathmin(relativeStart,len),end=arguments[2],relativeEnd=void 0===end?len:end>>0,final=0>relativeEnd?_Mathmax(len+relativeEnd,0):_Mathmin(relativeEnd,len);kp.x&&(minX=p.x),minY>p.y&&(minY=p.y)}var padding=this.opts.padding;maxX+=padding,maxY+=padding,minX-=padding,minY-=padding,this.drawingWidth=maxX-minX,this.drawingHeight=maxY-minY;var scaleX=this.canvas.offsetWidth/this.drawingWidth,scaleY=this.canvas.offsetHeight/this.drawingHeight,scale=scaleXalpha&&(ctx.globalAlpha=alpha),ctx.strokeStyle=gradient,ctx.stroke(),ctx.restore()}drawWedge(line,width=1){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,shortLine=line.clone().shorten(5),l=shortLine.getLeftVector().clone(),r=shortLine.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone(),l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),start=l,end=r;isRightChiralCenter&&(start=r,end=l);let t=Vector2.add(start,Vector2.multiplyScalar(normals[0],this.halfBondThickness)),u=Vector2.add(end,Vector2.multiplyScalar(normals[0],1.5+this.halfBondThickness)),v=Vector2.add(end,Vector2.multiplyScalar(normals[1],1.5+this.halfBondThickness)),w=Vector2.add(start,Vector2.multiplyScalar(normals[1],this.halfBondThickness));ctx.beginPath(),ctx.moveTo(t.x,t.y),ctx.lineTo(u.x,u.y),ctx.lineTo(v.x,v.y),ctx.lineTo(w.x,w.y);let gradient=this.ctx.createRadialGradient(r.x,r.y,this.opts.bondLength,r.x,r.y,0);gradient.addColorStop(.4,this.themeManager.getColor(line.getLeftElement())||this.themeManager.getColor("C")),gradient.addColorStop(.6,this.themeManager.getColor(line.getRightElement())||this.themeManager.getColor("C")),ctx.fillStyle=gradient,ctx.fill(),ctx.restore()}drawDashedWedge(line){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),shortLine=line.clone(),start,end,sStart,sEnd;isRightChiralCenter?(start=r,end=l,shortLine.shortenRight(1),sStart=shortLine.getRightVector().clone(),sEnd=shortLine.getLeftVector().clone()):(start=l,end=r,shortLine.shortenLeft(1),sStart=shortLine.getLeftVector().clone(),sEnd=shortLine.getRightVector().clone()),sStart.x+=offsetX,sStart.y+=offsetY,sEnd.x+=offsetX,sEnd.y+=offsetY;let dir=Vector2.subtract(end,start).normalize();ctx.strokeStyle=this.themeManager.getColor("C"),ctx.lineCap="round",ctx.lineWidth=this.opts.bondThickness,ctx.beginPath();let length=line.getLength(),step=1.25/(length/(3*this.opts.bondThickness)),changed=!1;for(var t=0;1>t;t+=step){let to=Vector2.multiplyScalar(dir,t*length),startDash=Vector2.add(start,to),width=1.5*t,dashOffset=Vector2.multiplyScalar(normals[0],width);!changed&&.5this.opts.fontSizeLarge?dim.width:this.opts.fontSizeLarge;r/=1.5,ctx.globalCompositeOperation="destination-out",ctx.beginPath(),ctx.arc(x+offsetX,y+offsetY,r,0,MathHelper.twoPI,!0),ctx.closePath(),ctx.fill(),ctx.globalCompositeOperation="source-over";let cursorPos=-dim.width/2,cursorPosLeft=-dim.width/2;ctx.fillStyle=this.themeManager.getColor(elementName),ctx.fillText(elementName,x+offsetX+cursorPos,y+this.opts.halfFontSizeLarge+offsetY),cursorPos+=dim.width,charge&&(ctx.font=this.fontSmall,ctx.fillText(chargeText,x+offsetX+cursorPos,y-this.opts.fifthFontSizeSmall+offsetY),cursorPos+=chargeWidth),0maxDist&&(maxDist=dist,a=i,b=j)}let angle=-Vector2.subtract(this.graph.vertices[a].position,this.graph.vertices[b].position).angle();if(!isNaN(angle)){let remainder=angle%.523599;.2617995>remainder?angle-=remainder:angle+=.523599-remainder;for(let i=0;i{if(counts.has(e)){let count=counts.get(e);molecularFormula+=e+(1vertexA.value.getRingbondCount()||1>vertexB.value.getRingbondCount())return null;for(var i=0;isubTreeDepthB&&(a=edge.sourceId,b=edge.targetId);let subTreeOverlap=this.getSubtreeOverlapScore(b,a,overlapScore.vertexScores);if(subTreeOverlap.value>this.opts.overlapSensitivity){let vertexA=this.graph.vertices[a],vertexB=this.graph.vertices[b],neighboursB=vertexB.getNeighbours(a);if(1===neighboursB.length){let neighbour=this.graph.vertices[neighboursB[0]],angle=neighbour.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbour.id,vertexB.id,angle,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?this.rotateSubtree(neighbour.id,vertexB.id,-angle,vertexB.position):this.totalOverlapScore=newTotalOverlapScore}else if(2===neighboursB.length){if(0!==vertexB.value.rings.length&&0!==vertexA.value.rings.length)continue;let neighbourA=this.graph.vertices[neighboursB[0]],neighbourB=this.graph.vertices[neighboursB[1]];if(1===neighbourA.value.rings.length&&1===neighbourB.value.rings.length){if(neighbourA.value.rings[0]!==neighbourB.value.rings[0])continue;}else if(0!==neighbourA.value.rings.length||0!==neighbourB.value.rings.length)continue;else{let angleA=neighbourA.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120)),angleB=neighbourB.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbourA.id,vertexB.id,angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,angleB,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?(this.rotateSubtree(neighbourA.id,vertexB.id,-angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,-angleB,vertexB.position)):this.totalOverlapScore=newTotalOverlapScore}}overlapScore=this.getOverlapScore()}}}this.resolveSecondaryOverlaps(overlapScore.scores),this.opts.isomeric&&this.annotateStereochemistry(),this.opts.compactDrawing&&"default"===this.opts.atomVisualization&&this.initPseudoElements(),this.rotateDrawing()}initRings(){let openBonds=new Map;for(let i=this.graph.vertices.length-1,vertex;0<=i;i--)if(vertex=this.graph.vertices[i],0!==vertex.value.ringbonds.length)for(let j=0;jneighbour.value.rings.length&&!neighbour.value.bridgedRing||neighbour.value.bridgedRing&&2>neighbour.value.originalRings.length)&&(vertex.value.isDrawn=!1)}}getBridgedRingRings(ringId){let involvedRings=[],that=this,recurse=function(r){let ring=that.getRing(r);involvedRings.push(r);for(let i=0,n;imaxSize&&(maxSize=size,largestCommonRing=ring)}return largestCommonRing}getVerticesAt(position,radius,excludeVertexId){let locals=[];for(let i=0,vertex;ii;){let a=this.graph.vertices[i],b=this.graph.vertices[j];if(!a.value.isDrawn||!b.value.isDrawn)continue;let dist=Vector2.subtract(a.position,b.position).lengthSq();if(disttotalSideCount[1]?0:1,sideCount:sideCount,position:sideCount[0]>sideCount[1]?0:1,anCount:anCount,bnCount:bnCount}}setRingCenter(ring){let ringSize=ring.getSize(),total=new Vector2(0,0);for(let i=0;is.sideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.sideCount[0]s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.totalSideCount[0]<=s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}}else if("#"===edge.bondType){normals[0].multiplyScalar(that.opts.bondSpacing/1.5),normals[1].multiplyScalar(that.opts.bondSpacing/1.5);let lineA=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)),lineB=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));this.canvasWrapper.drawLine(lineA),this.canvasWrapper.drawLine(lineB),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if("."===edge.bondType);else{let isChiralCenterA=vertexA.value.isStereoCenter,isChiralCenterB=vertexB.value.isStereoCenter;"up"===edge.wedge?this.canvasWrapper.drawWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):"down"===edge.wedge?this.canvasWrapper.drawDashedWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay)))}if(debug){let midpoint=Vector2.midpoint(a,b);this.canvasWrapper.drawDebugText(midpoint.x,midpoint.y,"e: "+edgeId)}}drawVertices(debug){for(let i=0;i_Mathabs(_MathPI-angle)&&this.canvasWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);this.canvasWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else;}if(this.opts.debug)for(let i=0,center;iring.rings.length)&&(vertex.angle=a,vertex.positioned=!0)},startVertexId,previousVertex?previousVertex.id:null);ring.positioned=!0,ring.center=center;for(let i=0,neighbour;iVector2.subtract(center,normals[0]).lengthSq()&&(nextCenter=normals[1]);let posA=Vector2.subtract(vertexA.position,nextCenter),posB=Vector2.subtract(vertexB.position,nextCenter);-1===posA.clockwise(posB)?!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexA,vertexB):!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexB,vertexA)}else if(1===vertices.length){ring.isSpiro=!0,neighbour.isSpiro=!0;let vertexA=this.graph.vertices[vertices[0]],nextCenter=Vector2.subtract(center,vertexA.position);nextCenter.invert(),nextCenter.normalize();let r=MathHelper.polyCircumradius(this.opts.bondLength,neighbour.getSize());nextCenter.multiplyScalar(r),nextCenter.add(vertexA.position),neighbour.positioned||this.createRing(neighbour,nextCenter,vertexA)}}for(let i=0;ithat.opts.overlapSensitivity&&(score+=s,count++);let position=that.graph.vertices[vertex.id].position.clone();position.multiplyScalar(s),center.add(position)}}),center.divide(score),{value:score/count,center:center}}getCurrentCenterOfMass(){let total=new Vector2(0,0),count=0;for(let i=0,vertex;itotal&&(this.rotateSubtree(a.id,overlap.common.id,2*angle,overlap.common.position),this.rotateSubtree(b.id,overlap.common.id,-2*angle,overlap.common.position))}else 1!==overlap.vertices.length||2!==overlap.rings.length}resolveSecondaryOverlaps(scores){for(let i=0;ithis.opts.overlapSensitivity){let vertex=this.graph.vertices[scores[i].id];if(vertex.isTerminal()){let closest=this.getClosestVertex(vertex);if(closest){let closestPosition=null;closestPosition=closest.isTerminal()?0===closest.id?this.graph.vertices[1].position:closest.previousPosition:0===closest.id?this.graph.vertices[1].position:closest.position;let vertexPreviousPosition=0===vertex.id?this.graph.vertices[1].position:vertex.previousPosition;vertex.position.rotateAwayFrom(closestPosition,vertexPreviousPosition,MathHelper.toRad(20))}}}}getLastVertexWithAngle(vertexId){let angle=0,vertex=null;for(;!angle&&vertexId;)vertex=this.graph.vertices[vertexId],angle=vertex.angle,vertexId=vertex.parentVertexId;return vertex}createNextBond(vertex,previousVertex=null,angle=0,originShortest=!1,skipPositioning=!1){if(vertex.positioned&&!skipPositioning)return;let doubleBondConfigSet=!1;if(previousVertex){let edge=this.graph.getEdge(vertex.id,previousVertex.id);("/"===edge.bondType||"\\"===edge.bondType)&&1==++this.doubleBondConfigCount%2&&null===this.doubleBondConfig&&(this.doubleBondConfig=edge.bondType,doubleBondConfigSet=!0,null===previousVertex.parentVertexId&&vertex.value.branchBond&&("/"===this.doubleBondConfig?this.doubleBondConfig="\\":"\\"===this.doubleBondConfig&&(this.doubleBondConfig="/")))}if(!skipPositioning)if(!previousVertex){let dummy=new Vector2(this.opts.bondLength,0);dummy.rotate(MathHelper.toRad(-60)),vertex.previousPosition=dummy,vertex.setPosition(this.opts.bondLength,0),vertex.angle=MathHelper.toRad(-60),null===vertex.value.bridgedRing&&(vertex.positioned=!0)}else if(0a?_Mathmax2(-1.0472,a):1.0472;else if(!a){let v=this.getLastVertexWithAngle(vertex.id);a=v.angle,a||(a=1.0472)}if(previousVertex&&!doubleBondConfigSet){let bondType=this.graph.getEdge(vertex.id,nextVertex.id).bondType;"/"===bondType?("/"===this.doubleBondConfig||"\\"===this.doubleBondConfig&&(a=-a),this.doubleBondConfig=null):"\\"===bondType&&("/"===this.doubleBondConfig?a=-a:"\\"===this.doubleBondConfig,this.doubleBondConfig=null)}nextVertex.angle=originShortest?a:-a,this.createNextBond(nextVertex,vertex,previousAngle+nextVertex.angle)}}else if(2===neighbours.length){let a=vertex.angle;a||(a=1.0472);let subTreeDepthA=this.graph.getTreeDepth(neighbours[0],vertex.id),subTreeDepthB=this.graph.getTreeDepth(neighbours[1],vertex.id),l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]];l.value.subtreeDepth=subTreeDepthA,r.value.subtreeDepth=subTreeDepthB;let subTreeDepthC=this.graph.getTreeDepth(previousVertex?previousVertex.id:null,vertex.id);previousVertex&&(previousVertex.value.subtreeDepth=subTreeDepthC);let cis=0,trans=1;"C"===r.value.element&&"C"!==l.value.element&&1subTreeDepthA?(cis=1,trans=0):"C"!==r.value.element&&"C"===l.value.element&&1subTreeDepthB?(cis=0,trans=1):subTreeDepthB>subTreeDepthA&&(cis=1,trans=0);let cisVertex=this.graph.vertices[neighbours[cis]],transVertex=this.graph.vertices[neighbours[trans]],originShortest=!1;subTreeDepthCd1&&d2>d3?(s=this.graph.vertices[neighbours[1]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[2]]):d3>d1&&d3>d2&&(s=this.graph.vertices[neighbours[2]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]]),previousVertex&&1>previousVertex.value.rings.length&&1>s.value.rings.length&&1>l.value.rings.length&&1>r.value.rings.length&&1===this.graph.getTreeDepth(l.id,vertex.id)&&1===this.graph.getTreeDepth(r.id,vertex.id)&&1d1&&d2>d3&&d2>d4?(w=this.graph.vertices[neighbours[1]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[2]],z=this.graph.vertices[neighbours[3]]):d3>d1&&d3>d2&&d3>d4?(w=this.graph.vertices[neighbours[2]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[3]]):d4>d1&&d4>d2&&d4>d3&&(w=this.graph.vertices[neighbours[3]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[2]]),w.angle=-MathHelper.toRad(36),x.angle=MathHelper.toRad(36),y.angle=-MathHelper.toRad(108),z.angle=MathHelper.toRad(108),this.createNextBond(w,vertex,previousAngle+w.angle),this.createNextBond(x,vertex,previousAngle+x.angle),this.createNextBond(y,vertex,previousAngle+y.angle),this.createNextBond(z,vertex,previousAngle+z.angle)}}}getCommonRingbondNeighbour(vertex){let neighbours=vertex.neighbours;for(let i=0,neighbour;imaxLevels&&(maxLevels=priorities[j][1].length);for(let k=0;kmaxEntries&&(maxEntries=priorities[j][1][k].length)}for(let j=0,diff;jb[1][j][k])return-1;if(a[1][j][k]b[0]?-1:a[0]vertex.getNeighbourCount()||0heteroAtomCount)continue;let previous=null;for(let j=0,neighbour;jr.x+this.opts.mouseTolerance)&&(mouseY>l.y-this.opts.mouseTolerance&&mouseYr.y-this.opts.mouseTolerance&&mouseY{e.setDecay(!1)}),this.decays.forEach(e=>{this.edges[e].setDecay(!0)})}standardDecays(){for(let i=0;i{this.edges[e].setDecay(!0),this.edges[e].setDecayAll(!0),this.decays.push(e),this.decaysAll.push(e)})}isDecayPoint(sourceId,targetId,edgeBondId,decayTypes=DecayPoint.VALUES.ALL){switch(decayTypes){case DecayPoint.VALUES.ALL:let found=this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);return!1===found?this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId):found;case DecayPoint.VALUES.COO:return this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId);case DecayPoint.VALUES.CONH:return this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);}}getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"O",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"O",edgeBondId)}getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"N",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"N",edgeBondId)}getNeighbourEdgeDecayId(vertexId,element,edgeBondId){for(let i=0,edgeId;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getSubgraphDistanceMatrix(vertexIds){let length=vertexIds.length,adja=this.getSubgraphAdjacencyMatrix(vertexIds),dist=Array(length);for(var i=0;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getAdjacencyList(){let length=this.vertices.length,adjacencyList=Array(length);for(var i=0;imax&&(max=d)}return max+1}traverseTree(vertexId,parentVertexId,callback,maxDepth=999999,ignoreFirst=!1,depth=1,visited=null){if(null===visited&&(visited=new Uint8Array(this.vertices.length)),depth>maxDepth+1||1===visited[vertexId])return;visited[vertexId]=1;let vertex=this.vertices[vertexId],neighbours=vertex.getNeighbours(parentVertexId);(!ignoreFirst||1maxEnergy&&!1===arrPositioned[i]&&(maxEnergy=delta,maxEnergyId=i,maxDEX=dEX,maxDEY=dEY)}return[maxEnergyId,maxEnergy,maxDEX,maxDEY]},update=function(index,dEX,dEY){let dxx=0,dyy=0,dxy=0,ux=arrPositionX[index],uy=arrPositionY[index],arrL=matLength[index],arrK=matStrength[index];for(i=length;i--;){if(i===index)continue;let vx=arrPositionX[i],vy=arrPositionY[i],l=arrL[i],k=arrK[i],m=(ux-vx)*(ux-vx),denom=1/_Mathpow(m+(uy-vy)*(uy-vy),1.5);dxx+=k*(1-l*(uy-vy)*(uy-vy)*denom),dyy+=k*(1-l*m*denom),dxy+=k*(l*(ux-vx)*(uy-vy)*denom)}0==dxx&&(dxx=.1),0===dyy&&(dyy=.1),0===dxy&&(dxy=.1);let dy=dEX/dxx+dEY/dxy;dy/=dxy/dxx-dyy/dxy;let dx=-(dxy*dy+dEX)/dxx;arrPositionX[index]+=dx,arrPositionY[index]+=dy;let arrE=matEnergy[index];dEX=0,dEY=0,ux=arrPositionX[index],uy=arrPositionY[index];let vx,vy,prevEx,prevEy,denom;for(i=length;i--;)index!==i&&(vx=arrPositionX[i],vy=arrPositionY[i],prevEx=arrE[i][0],prevEy=arrE[i][1],denom=1/_Mathsqrt2((ux-vx)*(ux-vx)+(uy-vy)*(uy-vy)),dx=arrK[i]*(ux-vx-arrL[i]*(ux-vx)*denom),dy=arrK[i]*(uy-vy-arrL[i]*(uy-vy)*denom),arrE[i]=[dx,dy],dEX+=dx,dEY+=dy,arrEnergySumX[i]+=dx-prevEx,arrEnergySumY[i]+=dy-prevEy);arrEnergySumX[index]=dEX,arrEnergySumY[index]=dEY},maxEnergyId=0,dEX=0,dEY=0,delta=0,iteration=0,innerIteration=0;for(;maxEnergy>threshold&&maxIteration>iteration;)for(iteration++,[maxEnergyId,maxEnergy,dEX,dEY]=highestEnergy(),delta=maxEnergy,innerIteration=0;delta>innerThreshold&&maxInnerIteration>innerIteration;)innerIteration++,update(maxEnergyId,dEX,dEY),[delta,dEX,dEY]=energy(maxEnergyId);for(i=length;i--;){let index=vertexIds[i],vertex=this.vertices[index];vertex.position.x=arrPositionX[i],vertex.position.y=arrPositionY[i],vertex.positioned=!0,vertex.forcePositioned=!0}}_bridgeDfs(u,visited,disc,low,parent,adj,outBridges){visited[u]=!0,disc[u]=low[u]=++this._time;for(var i=0;idisc[u]&&outBridges.push([u,v]))}}static getConnectedComponents(adjacencyMatrix){let length=adjacencyMatrix.length,visited=Array(length),components=[],count=0;visited.fill(!1);for(var u=0;u=sequence.length)return{sequence:sequence,smiles:smiles};for(char=sequence.charAt(position);!isNaN(char);){if(number+=char,++position,position>=sequence.length)return{sequence:sequence,smiles:smiles};char=sequence.charAt(position)}let j;for(j=0;j=sequence.length)break;char=sequence.charAt(position)}return{sequence:newSequence,smiles:newSmiles}}getSequencePermutation(sequence){let match=null,permutation=[];for(;null!=(match=/\d+/g.exec(sequence));)permutation.push(match);return permutation}dfsSmallStart(){this._smallGraph=new SmallGraph;for(let index=0;indexdecaysCounter.getValue()&&!0===isPolyketide.getValue()&&isPolyketide.setValue(through.every(vertex=>"O"===vertex||"N"===vertex)&&4this.vertices[lastVertexId].digits.includes(e))&&(vertex.digits.push(this._digitCounter),this.vertices[lastVertexId].digits.push(this._digitCounter),this._digitCounter++)),vertex.vertexState===VertexState.VALUES.NOT_FOUND)&&"H"!==vertex.value.element){this.first===vertex.id&&"C"===vertex.value.element&&isPolyketide.getValue()&&(stackSmiles.push("O"),isPolyketide.setValue(!1)),vertex.value.bracket?(stackSmiles.push("["),Graph.printVertexValue(stackSmiles,vertex),0vertex.value.bracket.charge&&stackSmiles.push(vertex.value.bracket.charge),stackSmiles.push("]")):Graph.printVertexValue(stackSmiles,vertex),vertexCounter.increment(),isSecondPass&&stackSmiles.push(this.smilesNumbersAdd(vertex)),this._markComponent||this._startingVertexes.push(vertex),vertex.component=this._cnt,this._markComponent=!0,vertex.vertexState=VertexState.VALUES.OPEN;for(let i=0;i=smiles.length)););index--,numbers.add(num)}return numbers}static findFirst(smiles,number){return smiles.indexOf(number)}static findSecond(smiles,from,number){let result=smiles.indexOf(number,from);if(-1===result)throw"Not Found";return result}smilesNumbersAdd(vertex){let numbers="";for(let i=0,num;ie===num)){let nextVertex=this.vertices.find(e=>e.digits.includes(num)&&e.id!==vertex.id),intersection=vertex.edges.filter(element=>nextVertex.edges.includes(element));if(0peg$maxFailPos&&(peg$maxFailPos=peg$currPos,peg$maxFailExpected=[]),peg$maxFailExpected.push(expected))}function peg$buildSimpleError(message,location){return new peg$SyntaxError(message,null,null,location)}function peg$parsechain(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;if(s0=peg$currPos,s1=peg$currPos,s2=peg$parseatom(),s2!==peg$FAILED){for(s3=[],s4=peg$parsebranch();s4!==peg$FAILED;)s3.push(s4),s4=peg$parsebranch();if(s3!==peg$FAILED){for(s4=[],s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));s5!==peg$FAILED;)s4.push(s5),s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));if(s4!==peg$FAILED){for(s5=[],s6=peg$parsebranch();s6!==peg$FAILED;)s5.push(s6),s6=peg$parsebranch();if(s5===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s7=peg$parsechain(),s7===peg$FAILED&&(s7=null),s7!==peg$FAILED){for(s8=[],s9=peg$parsebranch();s9!==peg$FAILED;)s8.push(s9),s9=peg$parsebranch();s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8],s1=s2)}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c0(s1)),s0=s1,s0}function peg$parsebranch(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,40===input.charCodeAt(peg$currPos)?(s2="(",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c2)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parsebond(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s4=peg$parsechain(),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(41===input.charCodeAt(peg$currPos)?(s5=")",peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c4)),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5],s1=s2)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c5(s1)),s0=s1,s0}function peg$parseatom(){var s0,s1;return s0=peg$currPos,s1=peg$parseorganicsymbol(),s1===peg$FAILED&&(s1=peg$parsearomaticsymbol(),s1===peg$FAILED&&(s1=peg$parsebracketatom(),s1===peg$FAILED&&(s1=peg$parsewildcard()))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsebond(){var s0,s1;if(s0=peg$currPos,peg$c7.test(input.charAt(peg$currPos))){if(s1=input.charAt(peg$currPos),s1===input.charAt(peg$currPos+1))throw s1=peg$FAILED,peg$buildSimpleError("The parser encountered a bond repetition.",peg$currPos+1);peg$currPos++}else s1=peg$FAILED,peg$fail(peg$c8);return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c9(s1)),s0=s1,s0}function peg$parsebracketatom(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;return s0=peg$currPos,s1=peg$currPos,91===input.charCodeAt(peg$currPos)?(s2="[",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c11)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parseisotope(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):("se"===input.substr(peg$currPos,2)?(s4="se",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c13)),s4===peg$FAILED&&("as"===input.substr(peg$currPos,2)?(s4="as",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c15)),s4===peg$FAILED&&(s4=peg$parsearomaticsymbol(),s4===peg$FAILED&&(s4=peg$parseelementsymbol(),s4===peg$FAILED&&(s4=peg$parsewildcard())))),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s5=peg$parsechiral(),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s6=peg$parsehcount(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s7=peg$parsecharge(),s7===peg$FAILED&&(s7=null),s7===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s8=peg$parseclass(),s8===peg$FAILED&&(s8=null),s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(93===input.charCodeAt(peg$currPos)?(s9="]",peg$currPos++):(s9=peg$FAILED,peg$fail(peg$c17)),s9===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8,s9],s1=s2)))))))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c18(s1)),s0=s1,s0}function peg$parseorganicsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,66===input.charCodeAt(peg$currPos)?(s2="B",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c20)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(114===input.charCodeAt(peg$currPos)?(s3="r",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c22)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(s1=peg$currPos,67===input.charCodeAt(peg$currPos)?(s2="C",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c24)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(108===input.charCodeAt(peg$currPos)?(s3="l",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c26)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(peg$c27.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c28)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c29(s1)),s0=s1,s0}function peg$parsearomaticsymbol(){var s0,s1;return s0=peg$currPos,peg$c30.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c31)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsewildcard(){var s0,s1;return s0=peg$currPos,42===input.charCodeAt(peg$currPos)?(s1="*",peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c33)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c34(s1)),s0=s1,s0}function peg$parseelementsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,peg$c35.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c36)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c37.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c38)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c39(s1)),s0=s1,s0}function peg$parsering(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,37===input.charCodeAt(peg$currPos)?(s2="%",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c41)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c43)),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1===peg$FAILED&&(peg$c44.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c45))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c46(s1)),s0=s1,s0}function peg$parsechiral(){var s0,s1,s2,s3,s4,s5,s6;return s0=peg$currPos,s1=peg$currPos,64===input.charCodeAt(peg$currPos)?(s2="@",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c48)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(64===input.charCodeAt(peg$currPos)?(s3="@",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c48)),s3===peg$FAILED&&(s3=peg$currPos,"TH"===input.substr(peg$currPos,2)?(s4="TH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c50)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"AL"===input.substr(peg$currPos,2)?(s4="AL",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c54)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"SP"===input.substr(peg$currPos,2)?(s4="SP",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c56)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c57.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c58)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"TB"===input.substr(peg$currPos,2)?(s4="TB",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c60)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4))),s3===peg$FAILED&&(s3=peg$currPos,"OH"===input.substr(peg$currPos,2)?(s4="OH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c62)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4)))))))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c63(s1)),s0=s1,s0}function peg$parsecharge(){var s0,s1;return s0=peg$currPos,s1=peg$parseposcharge(),s1===peg$FAILED&&(s1=peg$parsenegcharge()),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c64(s1)),s0=s1,s0}function peg$parseposcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,43===input.charCodeAt(peg$currPos)?(s2="+",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c66)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(43===input.charCodeAt(peg$currPos)?(s3="+",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c66)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c67(s1)),s0=s1,s0}function peg$parsenegcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,45===input.charCodeAt(peg$currPos)?(s2="-",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c69)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(45===input.charCodeAt(peg$currPos)?(s3="-",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c69)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c70(s1)),s0=s1,s0}function peg$parsehcount(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,72===input.charCodeAt(peg$currPos)?(s2="H",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c72)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c73(s1)),s0=s1,s0}function peg$parseclass(){var s0,s1,s2,s3,s4,s5,s6;if(s0=peg$currPos,s1=peg$currPos,58===input.charCodeAt(peg$currPos)?(s2=":",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c75)),s2!==peg$FAILED){if(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4!==peg$FAILED){for(s5=[],peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s6!==peg$FAILED;)s5.push(s6),peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)}else peg$currPos=s3,s3=peg$FAILED;s3===peg$FAILED&&(peg$c76.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c77))),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c78(s1)),s0=s1,s0}function peg$parseisotope(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c43)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED&&(s4=null),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c79(s1)),s0=s1,s0}options=void 0===options?{}:options;var nOpenParentheses=input.split("(").length-1,nCloseParentheses=input.split(")").length-1;if(nOpenParentheses!==nCloseParentheses)throw peg$buildSimpleError("The number of opening parentheses does not match the number of closing parentheses.",0);var peg$FAILED={},peg$startRuleFunctions={chain:peg$parsechain},peg$startRuleFunction=peg$parsechain,peg$c0=function(s){for(var branches=[],rings=[],i=0;imax;){let prev=current;callback(prev),current=vertices[current].getNextInRing(vertices,this.id,previousVertexId),previousVertexId=prev,current==startVertexId&&(current=null),max++}}getOrderedNeighbours(ringConnections){let orderedNeighbours=Array(this.neighbours.length);for(let i=0,vertices;inewPathLength){var l,m,n;if(previousPathLength===newPathLength+1)for(pe_prime[i][j]=[pe[i][j].length],l=pe[i][j].length;l--;)for(pe_prime[i][j][l]=[pe[i][j][l].length],m=pe[i][j][l].length;m--;)for(pe_prime[i][j][l][m]=[pe[i][j][l][m].length],n=pe[i][j][l][m].length;n--;)pe_prime[i][j][l][m][n]=[pe[i][j][l][m][0],pe[i][j][l][m][1]];else pe_prime[i][j]=[];for(d[i][j]=newPathLength,pe[i][j]=[[]],l=pe[i][k][0].length;l--;)pe[i][j][0].push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)pe[i][j][0].push(pe[k][j][0][l])}else if(previousPathLength===newPathLength){if(pe[i][k].length&&pe[k][j].length){var l;if(pe[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j][0]=tmp}}}else if(previousPathLength===newPathLength-1){var l;if(pe_prime[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j][0]=tmp}}}return{d:d,pe:pe,pe_prime:pe_prime}}static getRingCandidates(d,pe,pe_prime){let length=d.length,candidates=[],c=0;for(let i=0;insssr)return cSssr}else for(let j=0,bonds;jnsssr)return cSssr}return cSssr}static getEdgeCount(adjacencyMatrix){let edgeCount=0,length=adjacencyMatrix.length;for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeCount++;return edgeCount}static getEdgeList(adjacencyMatrix){let length=adjacencyMatrix.length,edgeList=[];for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeList.push([i,j]);return edgeList}static bondsToAtoms(bonds){let atoms=new Set;for(var i=bonds.length;i--;)atoms.add(bonds[i][0]),atoms.add(bonds[i][1]);return atoms}static getBondCount(atoms,adjacencyMatrix){let count=0;for(let u of atoms)for(let v of atoms)u!==v&&(count+=adjacencyMatrix[u][v]);return count/2}static pathSetsContain(pathSets,pathSet,bonds,allBonds,arrBondCount,arrRingCount){for(var i=pathSets.length;i--;){if(SSSR.isSupersetOf(pathSet,pathSets[i]))return!0;if(pathSets[i].size===pathSet.size&&SSSR.areSetsEqual(pathSets[i],pathSet))return!0}let count=0,allContained=!1;for(i=bonds.length;i--;)for(var j=allBonds.length;j--;)(bonds[i][0]===allBonds[j][0]&&bonds[i][1]===allBonds[j][1]||bonds[i][1]===allBonds[j][0]&&bonds[i][0]===allBonds[j][1])&&count++,count===bonds.length&&(allContained=!0);let specialCase=!1;if(allContained)for(let element of pathSet)if(arrRingCount[element]e.vertexState=VertexState.VALUES.NOT_FOUND)}getSourceNode(){let ends=[];for(let index=0;indexthis._nodes[v].onRing=!0);continue}node.neighbours.forEach(neighbour=>{if(!path.some(e=>e===neighbour.neighbour)||neighbour.neighbour===start.id){let newPath=[...path];newPath.push(neighbour.neighbour),queue.push(newPath)}}),firstPass=!1}}sortByRingPreference(array){let sortedArray=[...array];return sortedArray.sort((a,b)=>this._nodes[a.neighbour].onRing===this._nodes[b.neighbour].onRing?a.direction>b.direction?-1:a.direction{let edges=graph.getEdges(vertex.id);for(var i=0;is.sideCount[1]||s.totalSideCount[0]>s.totalSideCount[1]){this.multiplyNormals(normals,opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB);line.shorten(opts.bondLength-opts.shortBondLength*opts.bondLength),svgWrapper.drawLine(line),svgWrapper.drawLine(new Line(a,b,elementA,elementB))}else if(s.sideCount[0]_Mathabs2(_MathPI3-angle)&&svgWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,vertex.value.chirality)}if(opts.debug)for(var i=0;i{const context=canvas.getContext("2d");context.clearRect(0,0,canvas.width,canvas.height)})},SmilesDrawer.parse=function(smiles,successCallback,errorCallback){try{successCallback&&successCallback(Parser.parse(smiles))}catch(err){errorCallback&&errorCallback(err)}},canUseDOM&&(window.SmilesDrawer=SmilesDrawer),Array.prototype.fill||Object.defineProperty(Array.prototype,"fill",{value:function(value){if(null==this)throw new TypeError("this is null or not defined");for(var O=Object(this),len=O.length>>>0,start=arguments[1],relativeStart=start>>0,k=0>relativeStart?_Mathmax(len+relativeStart,0):_Mathmin(relativeStart,len),end=arguments[2],relativeEnd=void 0===end?len:end>>0,final=0>relativeEnd?_Mathmax(len+relativeEnd,0):_Mathmin(relativeEnd,len);kp.x&&(minX=p.x),minY>p.y&&(minY=p.y)}var padding=this.opts.padding;maxX+=padding,maxY+=padding,minX-=padding,minY-=padding,this.drawingWidth=maxX-minX,this.drawingHeight=maxY-minY;var scaleX=this.canvas.offsetWidth/this.drawingWidth,scaleY=this.canvas.offsetHeight/this.drawingHeight,scale=scaleXalpha&&(ctx.globalAlpha=alpha),ctx.strokeStyle=gradient,ctx.stroke(),ctx.restore()}drawWedge(line,width=1){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,shortLine=line.clone().shorten(5),l=shortLine.getLeftVector().clone(),r=shortLine.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone(),l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),start=l,end=r;isRightChiralCenter&&(start=r,end=l);let t=Vector2.add(start,Vector2.multiplyScalar(normals[0],this.halfBondThickness)),u=Vector2.add(end,Vector2.multiplyScalar(normals[0],1.5+this.halfBondThickness)),v=Vector2.add(end,Vector2.multiplyScalar(normals[1],1.5+this.halfBondThickness)),w=Vector2.add(start,Vector2.multiplyScalar(normals[1],this.halfBondThickness));ctx.beginPath(),ctx.moveTo(t.x,t.y),ctx.lineTo(u.x,u.y),ctx.lineTo(v.x,v.y),ctx.lineTo(w.x,w.y);let gradient=this.ctx.createRadialGradient(r.x,r.y,this.opts.bondLength,r.x,r.y,0);gradient.addColorStop(.4,this.themeManager.getColor(line.getLeftElement())||this.themeManager.getColor("C")),gradient.addColorStop(.6,this.themeManager.getColor(line.getRightElement())||this.themeManager.getColor("C")),ctx.fillStyle=gradient,ctx.fill(),ctx.restore()}drawDashedWedge(line){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),shortLine=line.clone(),start,end,sStart,sEnd;isRightChiralCenter?(start=r,end=l,shortLine.shortenRight(1),sStart=shortLine.getRightVector().clone(),sEnd=shortLine.getLeftVector().clone()):(start=l,end=r,shortLine.shortenLeft(1),sStart=shortLine.getLeftVector().clone(),sEnd=shortLine.getRightVector().clone()),sStart.x+=offsetX,sStart.y+=offsetY,sEnd.x+=offsetX,sEnd.y+=offsetY;let dir=Vector2.subtract(end,start).normalize();ctx.strokeStyle=this.themeManager.getColor("C"),ctx.lineCap="round",ctx.lineWidth=this.opts.bondThickness,ctx.beginPath();let length=line.getLength(),step=1.25/(length/(3*this.opts.bondThickness)),changed=!1;for(var t=0;1>t;t+=step){let to=Vector2.multiplyScalar(dir,t*length),startDash=Vector2.add(start,to),width=1.5*t,dashOffset=Vector2.multiplyScalar(normals[0],width);!changed&&.5this.opts.fontSizeLarge?dim.width:this.opts.fontSizeLarge;r/=1.5,ctx.globalCompositeOperation="destination-out",ctx.beginPath(),ctx.arc(x+offsetX,y+offsetY,r,0,MathHelper.twoPI,!0),ctx.closePath(),ctx.fill(),ctx.globalCompositeOperation="source-over";let cursorPos=-dim.width/2,cursorPosLeft=-dim.width/2;ctx.fillStyle=this.themeManager.getColor(elementName),ctx.fillText(elementName,x+offsetX+cursorPos,y+this.opts.halfFontSizeLarge+offsetY),cursorPos+=dim.width,charge&&(ctx.font=this.fontSmall,ctx.fillText(chargeText,x+offsetX+cursorPos,y-this.opts.fifthFontSizeSmall+offsetY),cursorPos+=chargeWidth),0maxDist&&(maxDist=dist,a=i,b=j)}let angle=-Vector2.subtract(this.graph.vertices[a].position,this.graph.vertices[b].position).angle();if(!isNaN(angle)){let remainder=angle%.523599;.2617995>remainder?angle-=remainder:angle+=.523599-remainder;for(let i=0;i{if(counts.has(e)){let count=counts.get(e);molecularFormula+=e+(1vertexA.value.getRingbondCount()||1>vertexB.value.getRingbondCount())return null;for(var i=0;isubTreeDepthB&&(a=edge.sourceId,b=edge.targetId);let subTreeOverlap=this.getSubtreeOverlapScore(b,a,overlapScore.vertexScores);if(subTreeOverlap.value>this.opts.overlapSensitivity){let vertexA=this.graph.vertices[a],vertexB=this.graph.vertices[b],neighboursB=vertexB.getNeighbours(a);if(1===neighboursB.length){let neighbour=this.graph.vertices[neighboursB[0]],angle=neighbour.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbour.id,vertexB.id,angle,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?this.rotateSubtree(neighbour.id,vertexB.id,-angle,vertexB.position):this.totalOverlapScore=newTotalOverlapScore}else if(2===neighboursB.length){if(0!==vertexB.value.rings.length&&0!==vertexA.value.rings.length)continue;let neighbourA=this.graph.vertices[neighboursB[0]],neighbourB=this.graph.vertices[neighboursB[1]];if(1===neighbourA.value.rings.length&&1===neighbourB.value.rings.length){if(neighbourA.value.rings[0]!==neighbourB.value.rings[0])continue;}else if(0!==neighbourA.value.rings.length||0!==neighbourB.value.rings.length)continue;else{let angleA=neighbourA.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120)),angleB=neighbourB.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbourA.id,vertexB.id,angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,angleB,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?(this.rotateSubtree(neighbourA.id,vertexB.id,-angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,-angleB,vertexB.position)):this.totalOverlapScore=newTotalOverlapScore}}overlapScore=this.getOverlapScore()}}}this.resolveSecondaryOverlaps(overlapScore.scores),this.opts.isomeric&&this.annotateStereochemistry(),this.opts.compactDrawing&&"default"===this.opts.atomVisualization&&this.initPseudoElements(),this.rotateDrawing()}initRings(){let openBonds=new Map;for(let i=this.graph.vertices.length-1,vertex;0<=i;i--)if(vertex=this.graph.vertices[i],0!==vertex.value.ringbonds.length)for(let j=0;jneighbour.value.rings.length&&!neighbour.value.bridgedRing||neighbour.value.bridgedRing&&2>neighbour.value.originalRings.length)&&(vertex.value.isDrawn=!1)}}getBridgedRingRings(ringId){let involvedRings=[],that=this,recurse=function(r){let ring=that.getRing(r);involvedRings.push(r);for(let i=0,n;imaxSize&&(maxSize=size,largestCommonRing=ring)}return largestCommonRing}getVerticesAt(position,radius,excludeVertexId){let locals=[];for(let i=0,vertex;ii;){let a=this.graph.vertices[i],b=this.graph.vertices[j];if(!a.value.isDrawn||!b.value.isDrawn)continue;let dist=Vector2.subtract(a.position,b.position).lengthSq();if(disttotalSideCount[1]?0:1,sideCount:sideCount,position:sideCount[0]>sideCount[1]?0:1,anCount:anCount,bnCount:bnCount}}setRingCenter(ring){let ringSize=ring.getSize(),total=new Vector2(0,0);for(let i=0;is.sideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.sideCount[0]s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.totalSideCount[0]<=s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}}else if("#"===edge.bondType){normals[0].multiplyScalar(that.opts.bondSpacing/1.5),normals[1].multiplyScalar(that.opts.bondSpacing/1.5);let lineA=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)),lineB=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));this.canvasWrapper.drawLine(lineA),this.canvasWrapper.drawLine(lineB),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if("."===edge.bondType);else{let isChiralCenterA=vertexA.value.isStereoCenter,isChiralCenterB=vertexB.value.isStereoCenter;"up"===edge.wedge?this.canvasWrapper.drawWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):"down"===edge.wedge?this.canvasWrapper.drawDashedWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay)))}if(debug){let midpoint=Vector2.midpoint(a,b);this.canvasWrapper.drawDebugText(midpoint.x,midpoint.y,"e: "+edgeId)}}drawVertices(debug){for(let i=0;i_Mathabs(_MathPI-angle)&&this.canvasWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);this.canvasWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else;}if(this.opts.debug)for(let i=0,center;iring.rings.length)&&(vertex.angle=a,vertex.positioned=!0)},startVertexId,previousVertex?previousVertex.id:null);ring.positioned=!0,ring.center=center;for(let i=0,neighbour;iVector2.subtract(center,normals[0]).lengthSq()&&(nextCenter=normals[1]);let posA=Vector2.subtract(vertexA.position,nextCenter),posB=Vector2.subtract(vertexB.position,nextCenter);-1===posA.clockwise(posB)?!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexA,vertexB):!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexB,vertexA)}else if(1===vertices.length){ring.isSpiro=!0,neighbour.isSpiro=!0;let vertexA=this.graph.vertices[vertices[0]],nextCenter=Vector2.subtract(center,vertexA.position);nextCenter.invert(),nextCenter.normalize();let r=MathHelper.polyCircumradius(this.opts.bondLength,neighbour.getSize());nextCenter.multiplyScalar(r),nextCenter.add(vertexA.position),neighbour.positioned||this.createRing(neighbour,nextCenter,vertexA)}}for(let i=0;ithat.opts.overlapSensitivity&&(score+=s,count++);let position=that.graph.vertices[vertex.id].position.clone();position.multiplyScalar(s),center.add(position)}}),center.divide(score),{value:score/count,center:center}}getCurrentCenterOfMass(){let total=new Vector2(0,0),count=0;for(let i=0,vertex;itotal&&(this.rotateSubtree(a.id,overlap.common.id,2*angle,overlap.common.position),this.rotateSubtree(b.id,overlap.common.id,-2*angle,overlap.common.position))}else 1!==overlap.vertices.length||2!==overlap.rings.length}resolveSecondaryOverlaps(scores){for(let i=0;ithis.opts.overlapSensitivity){let vertex=this.graph.vertices[scores[i].id];if(vertex.isTerminal()){let closest=this.getClosestVertex(vertex);if(closest){let closestPosition=null;closestPosition=closest.isTerminal()?0===closest.id?this.graph.vertices[1].position:closest.previousPosition:0===closest.id?this.graph.vertices[1].position:closest.position;let vertexPreviousPosition=0===vertex.id?this.graph.vertices[1].position:vertex.previousPosition;vertex.position.rotateAwayFrom(closestPosition,vertexPreviousPosition,MathHelper.toRad(20))}}}}getLastVertexWithAngle(vertexId){let angle=0,vertex=null;for(;!angle&&vertexId;)vertex=this.graph.vertices[vertexId],angle=vertex.angle,vertexId=vertex.parentVertexId;return vertex}createNextBond(vertex,previousVertex=null,angle=0,originShortest=!1,skipPositioning=!1){if(vertex.positioned&&!skipPositioning)return;let doubleBondConfigSet=!1;if(previousVertex){let edge=this.graph.getEdge(vertex.id,previousVertex.id);("/"===edge.bondType||"\\"===edge.bondType)&&1==++this.doubleBondConfigCount%2&&null===this.doubleBondConfig&&(this.doubleBondConfig=edge.bondType,doubleBondConfigSet=!0,null===previousVertex.parentVertexId&&vertex.value.branchBond&&("/"===this.doubleBondConfig?this.doubleBondConfig="\\":"\\"===this.doubleBondConfig&&(this.doubleBondConfig="/")))}if(!skipPositioning)if(!previousVertex){let dummy=new Vector2(this.opts.bondLength,0);dummy.rotate(MathHelper.toRad(-60)),vertex.previousPosition=dummy,vertex.setPosition(this.opts.bondLength,0),vertex.angle=MathHelper.toRad(-60),null===vertex.value.bridgedRing&&(vertex.positioned=!0)}else if(0a?_Mathmax2(-1.0472,a):1.0472;else if(!a){let v=this.getLastVertexWithAngle(vertex.id);a=v.angle,a||(a=1.0472)}if(previousVertex&&!doubleBondConfigSet){let bondType=this.graph.getEdge(vertex.id,nextVertex.id).bondType;"/"===bondType?("/"===this.doubleBondConfig||"\\"===this.doubleBondConfig&&(a=-a),this.doubleBondConfig=null):"\\"===bondType&&("/"===this.doubleBondConfig?a=-a:"\\"===this.doubleBondConfig,this.doubleBondConfig=null)}nextVertex.angle=originShortest?a:-a,this.createNextBond(nextVertex,vertex,previousAngle+nextVertex.angle)}}else if(2===neighbours.length){let a=vertex.angle;a||(a=1.0472);let subTreeDepthA=this.graph.getTreeDepth(neighbours[0],vertex.id),subTreeDepthB=this.graph.getTreeDepth(neighbours[1],vertex.id),l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]];l.value.subtreeDepth=subTreeDepthA,r.value.subtreeDepth=subTreeDepthB;let subTreeDepthC=this.graph.getTreeDepth(previousVertex?previousVertex.id:null,vertex.id);previousVertex&&(previousVertex.value.subtreeDepth=subTreeDepthC);let cis=0,trans=1;"C"===r.value.element&&"C"!==l.value.element&&1subTreeDepthA?(cis=1,trans=0):"C"!==r.value.element&&"C"===l.value.element&&1subTreeDepthB?(cis=0,trans=1):subTreeDepthB>subTreeDepthA&&(cis=1,trans=0);let cisVertex=this.graph.vertices[neighbours[cis]],transVertex=this.graph.vertices[neighbours[trans]],originShortest=!1;subTreeDepthCd1&&d2>d3?(s=this.graph.vertices[neighbours[1]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[2]]):d3>d1&&d3>d2&&(s=this.graph.vertices[neighbours[2]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]]),previousVertex&&1>previousVertex.value.rings.length&&1>s.value.rings.length&&1>l.value.rings.length&&1>r.value.rings.length&&1===this.graph.getTreeDepth(l.id,vertex.id)&&1===this.graph.getTreeDepth(r.id,vertex.id)&&1d1&&d2>d3&&d2>d4?(w=this.graph.vertices[neighbours[1]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[2]],z=this.graph.vertices[neighbours[3]]):d3>d1&&d3>d2&&d3>d4?(w=this.graph.vertices[neighbours[2]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[3]]):d4>d1&&d4>d2&&d4>d3&&(w=this.graph.vertices[neighbours[3]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[2]]),w.angle=-MathHelper.toRad(36),x.angle=MathHelper.toRad(36),y.angle=-MathHelper.toRad(108),z.angle=MathHelper.toRad(108),this.createNextBond(w,vertex,previousAngle+w.angle),this.createNextBond(x,vertex,previousAngle+x.angle),this.createNextBond(y,vertex,previousAngle+y.angle),this.createNextBond(z,vertex,previousAngle+z.angle)}}}getCommonRingbondNeighbour(vertex){let neighbours=vertex.neighbours;for(let i=0,neighbour;imaxLevels&&(maxLevels=priorities[j][1].length);for(let k=0;kmaxEntries&&(maxEntries=priorities[j][1][k].length)}for(let j=0,diff;jb[1][j][k])return-1;if(a[1][j][k]b[0]?-1:a[0]vertex.getNeighbourCount()||0heteroAtomCount)continue;let previous=null;for(let j=0,neighbour;jr.x+this.opts.mouseTolerance)&&(mouseY>l.y-this.opts.mouseTolerance&&mouseYr.y-this.opts.mouseTolerance&&mouseY{e.setDecay(!1)}),this.decays.forEach(e=>{this.edges[e].setDecay(!0)})}standardDecays(){for(let i=0;i{this.edges[e].setDecay(!0),this.edges[e].setDecayAll(!0),this.decays.push(e),this.decaysAll.push(e)})}isDecayPoint(sourceId,targetId,edgeBondId,decayTypes=DecayPoint.VALUES.ALL){switch(decayTypes){case DecayPoint.VALUES.ALL:let found=this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);return!1===found?this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId):found;case DecayPoint.VALUES.COO:return this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId);case DecayPoint.VALUES.CONH:return this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);}}getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"O",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"O",edgeBondId)}getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"N",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"N",edgeBondId)}getNeighbourEdgeDecayId(vertexId,element,edgeBondId){for(let i=0,edgeId;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getSubgraphDistanceMatrix(vertexIds){let length=vertexIds.length,adja=this.getSubgraphAdjacencyMatrix(vertexIds),dist=Array(length);for(var i=0;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getAdjacencyList(){let length=this.vertices.length,adjacencyList=Array(length);for(var i=0;imax&&(max=d)}return max+1}traverseTree(vertexId,parentVertexId,callback,maxDepth=999999,ignoreFirst=!1,depth=1,visited=null){if(null===visited&&(visited=new Uint8Array(this.vertices.length)),depth>maxDepth+1||1===visited[vertexId])return;visited[vertexId]=1;let vertex=this.vertices[vertexId],neighbours=vertex.getNeighbours(parentVertexId);(!ignoreFirst||1maxEnergy&&!1===arrPositioned[i]&&(maxEnergy=delta,maxEnergyId=i,maxDEX=dEX,maxDEY=dEY)}return[maxEnergyId,maxEnergy,maxDEX,maxDEY]},update=function(index,dEX,dEY){let dxx=0,dyy=0,dxy=0,ux=arrPositionX[index],uy=arrPositionY[index],arrL=matLength[index],arrK=matStrength[index];for(i=length;i--;){if(i===index)continue;let vx=arrPositionX[i],vy=arrPositionY[i],l=arrL[i],k=arrK[i],m=(ux-vx)*(ux-vx),denom=1/_Mathpow(m+(uy-vy)*(uy-vy),1.5);dxx+=k*(1-l*(uy-vy)*(uy-vy)*denom),dyy+=k*(1-l*m*denom),dxy+=k*(l*(ux-vx)*(uy-vy)*denom)}0==dxx&&(dxx=.1),0===dyy&&(dyy=.1),0===dxy&&(dxy=.1);let dy=dEX/dxx+dEY/dxy;dy/=dxy/dxx-dyy/dxy;let dx=-(dxy*dy+dEX)/dxx;arrPositionX[index]+=dx,arrPositionY[index]+=dy;let arrE=matEnergy[index];dEX=0,dEY=0,ux=arrPositionX[index],uy=arrPositionY[index];let vx,vy,prevEx,prevEy,denom;for(i=length;i--;)index!==i&&(vx=arrPositionX[i],vy=arrPositionY[i],prevEx=arrE[i][0],prevEy=arrE[i][1],denom=1/_Mathsqrt2((ux-vx)*(ux-vx)+(uy-vy)*(uy-vy)),dx=arrK[i]*(ux-vx-arrL[i]*(ux-vx)*denom),dy=arrK[i]*(uy-vy-arrL[i]*(uy-vy)*denom),arrE[i]=[dx,dy],dEX+=dx,dEY+=dy,arrEnergySumX[i]+=dx-prevEx,arrEnergySumY[i]+=dy-prevEy);arrEnergySumX[index]=dEX,arrEnergySumY[index]=dEY},maxEnergyId=0,dEX=0,dEY=0,delta=0,iteration=0,innerIteration=0;for(;maxEnergy>threshold&&maxIteration>iteration;)for(iteration++,[maxEnergyId,maxEnergy,dEX,dEY]=highestEnergy(),delta=maxEnergy,innerIteration=0;delta>innerThreshold&&maxInnerIteration>innerIteration;)innerIteration++,update(maxEnergyId,dEX,dEY),[delta,dEX,dEY]=energy(maxEnergyId);for(i=length;i--;){let index=vertexIds[i],vertex=this.vertices[index];vertex.position.x=arrPositionX[i],vertex.position.y=arrPositionY[i],vertex.positioned=!0,vertex.forcePositioned=!0}}_bridgeDfs(u,visited,disc,low,parent,adj,outBridges){visited[u]=!0,disc[u]=low[u]=++this._time;for(var i=0;idisc[u]&&outBridges.push([u,v]))}}static getConnectedComponents(adjacencyMatrix){let length=adjacencyMatrix.length,visited=Array(length),components=[],count=0;visited.fill(!1);for(var u=0;u=sequence.length)return{sequence:sequence,smiles:smiles};for(char=sequence.charAt(position);!isNaN(char);){if(number+=char,++position,position>=sequence.length)return{sequence:sequence,smiles:smiles};char=sequence.charAt(position)}let j;for(j=0;j=sequence.length)break;char=sequence.charAt(position)}return{sequence:newSequence,smiles:newSmiles}}getSequencePermutation(sequence){let match=null,permutation=[];for(;null!=(match=/\d+/g.exec(sequence));)permutation.push(match);return permutation}dfsSmallStart(){this._smallGraph=new SmallGraph;for(let index=0;indexdecaysCounter.getValue()&&!0===isPolyketide.getValue()&&isPolyketide.setValue(through.every(vertex=>"O"===vertex||"N"===vertex)&&4this.vertices[lastVertexId].digits.includes(e))&&(vertex.digits.push(this._digitCounter),this.vertices[lastVertexId].digits.push(this._digitCounter),this._digitCounter++)),vertex.vertexState===VertexState.VALUES.NOT_FOUND)&&"H"!==vertex.value.element){this.first===vertex.id&&"C"===vertex.value.element&&isPolyketide.getValue()&&(stackSmiles.push("O"),isPolyketide.setValue(!1)),vertex.value.bracket?(stackSmiles.push("["),Graph.printVertexValue(stackSmiles,vertex),0vertex.value.bracket.charge&&stackSmiles.push(vertex.value.bracket.charge),stackSmiles.push("]")):Graph.printVertexValue(stackSmiles,vertex),vertexCounter.increment(),isSecondPass&&stackSmiles.push(this.smilesNumbersAdd(vertex)),this._markComponent||this._startingVertexes.push(vertex),vertex.component=this._cnt,this._markComponent=!0,vertex.vertexState=VertexState.VALUES.OPEN;for(let i=0;i=smiles.length)););index--,numbers.add(num)}return numbers}static findFirst(smiles,number){return smiles.indexOf(number)}static findSecond(smiles,from,number){let result=smiles.indexOf(number,from);if(-1===result)throw"Not Found";return result}smilesNumbersAdd(vertex){let numbers="";for(let i=0,num;ie===num)){let nextVertex=this.vertices.find(e=>e.digits.includes(num)&&e.id!==vertex.id),intersection=vertex.edges.filter(element=>nextVertex.edges.includes(element));if(0peg$maxFailPos&&(peg$maxFailPos=peg$currPos,peg$maxFailExpected=[]),peg$maxFailExpected.push(expected))}function peg$buildSimpleError(message,location){return new peg$SyntaxError(message,null,null,location)}function peg$parsechain(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;if(s0=peg$currPos,s1=peg$currPos,s2=peg$parseatom(),s2!==peg$FAILED){for(s3=[],s4=peg$parsebranch();s4!==peg$FAILED;)s3.push(s4),s4=peg$parsebranch();if(s3!==peg$FAILED){for(s4=[],s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));s5!==peg$FAILED;)s4.push(s5),s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));if(s4!==peg$FAILED){for(s5=[],s6=peg$parsebranch();s6!==peg$FAILED;)s5.push(s6),s6=peg$parsebranch();if(s5===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s7=peg$parsechain(),s7===peg$FAILED&&(s7=null),s7!==peg$FAILED){for(s8=[],s9=peg$parsebranch();s9!==peg$FAILED;)s8.push(s9),s9=peg$parsebranch();s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8],s1=s2)}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c0(s1)),s0=s1,s0}function peg$parsebranch(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,40===input.charCodeAt(peg$currPos)?(s2="(",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c2)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parsebond(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s4=peg$parsechain(),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(41===input.charCodeAt(peg$currPos)?(s5=")",peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c4)),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5],s1=s2)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c5(s1)),s0=s1,s0}function peg$parseatom(){var s0,s1;return s0=peg$currPos,s1=peg$parseorganicsymbol(),s1===peg$FAILED&&(s1=peg$parsearomaticsymbol(),s1===peg$FAILED&&(s1=peg$parsebracketatom(),s1===peg$FAILED&&(s1=peg$parsewildcard()))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsebond(){var s0,s1;if(s0=peg$currPos,peg$c7.test(input.charAt(peg$currPos))){if(s1=input.charAt(peg$currPos),s1===input.charAt(peg$currPos+1))throw s1=peg$FAILED,peg$buildSimpleError("The parser encountered a bond repetition.",peg$currPos+1);peg$currPos++}else s1=peg$FAILED,peg$fail(peg$c8);return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c9(s1)),s0=s1,s0}function peg$parsebracketatom(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;return s0=peg$currPos,s1=peg$currPos,91===input.charCodeAt(peg$currPos)?(s2="[",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c11)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parseisotope(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):("se"===input.substr(peg$currPos,2)?(s4="se",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c13)),s4===peg$FAILED&&("as"===input.substr(peg$currPos,2)?(s4="as",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c15)),s4===peg$FAILED&&(s4=peg$parsearomaticsymbol(),s4===peg$FAILED&&(s4=peg$parseelementsymbol(),s4===peg$FAILED&&(s4=peg$parsewildcard())))),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s5=peg$parsechiral(),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s6=peg$parsehcount(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s7=peg$parsecharge(),s7===peg$FAILED&&(s7=null),s7===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s8=peg$parseclass(),s8===peg$FAILED&&(s8=null),s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(93===input.charCodeAt(peg$currPos)?(s9="]",peg$currPos++):(s9=peg$FAILED,peg$fail(peg$c17)),s9===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8,s9],s1=s2)))))))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c18(s1)),s0=s1,s0}function peg$parseorganicsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,66===input.charCodeAt(peg$currPos)?(s2="B",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c20)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(114===input.charCodeAt(peg$currPos)?(s3="r",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c22)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(s1=peg$currPos,67===input.charCodeAt(peg$currPos)?(s2="C",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c24)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(108===input.charCodeAt(peg$currPos)?(s3="l",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c26)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(peg$c27.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c28)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c29(s1)),s0=s1,s0}function peg$parsearomaticsymbol(){var s0,s1;return s0=peg$currPos,peg$c30.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c31)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsewildcard(){var s0,s1;return s0=peg$currPos,42===input.charCodeAt(peg$currPos)?(s1="*",peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c33)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c34(s1)),s0=s1,s0}function peg$parseelementsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,peg$c35.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c36)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c37.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c38)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c39(s1)),s0=s1,s0}function peg$parsering(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,37===input.charCodeAt(peg$currPos)?(s2="%",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c41)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c43)),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1===peg$FAILED&&(peg$c44.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c45))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c46(s1)),s0=s1,s0}function peg$parsechiral(){var s0,s1,s2,s3,s4,s5,s6;return s0=peg$currPos,s1=peg$currPos,64===input.charCodeAt(peg$currPos)?(s2="@",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c48)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(64===input.charCodeAt(peg$currPos)?(s3="@",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c48)),s3===peg$FAILED&&(s3=peg$currPos,"TH"===input.substr(peg$currPos,2)?(s4="TH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c50)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"AL"===input.substr(peg$currPos,2)?(s4="AL",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c54)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"SP"===input.substr(peg$currPos,2)?(s4="SP",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c56)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c57.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c58)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"TB"===input.substr(peg$currPos,2)?(s4="TB",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c60)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4))),s3===peg$FAILED&&(s3=peg$currPos,"OH"===input.substr(peg$currPos,2)?(s4="OH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c62)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4)))))))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c63(s1)),s0=s1,s0}function peg$parsecharge(){var s0,s1;return s0=peg$currPos,s1=peg$parseposcharge(),s1===peg$FAILED&&(s1=peg$parsenegcharge()),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c64(s1)),s0=s1,s0}function peg$parseposcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,43===input.charCodeAt(peg$currPos)?(s2="+",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c66)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(43===input.charCodeAt(peg$currPos)?(s3="+",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c66)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c67(s1)),s0=s1,s0}function peg$parsenegcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,45===input.charCodeAt(peg$currPos)?(s2="-",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c69)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(45===input.charCodeAt(peg$currPos)?(s3="-",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c69)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c70(s1)),s0=s1,s0}function peg$parsehcount(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,72===input.charCodeAt(peg$currPos)?(s2="H",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c72)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c73(s1)),s0=s1,s0}function peg$parseclass(){var s0,s1,s2,s3,s4,s5,s6;if(s0=peg$currPos,s1=peg$currPos,58===input.charCodeAt(peg$currPos)?(s2=":",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c75)),s2!==peg$FAILED){if(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4!==peg$FAILED){for(s5=[],peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s6!==peg$FAILED;)s5.push(s6),peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)}else peg$currPos=s3,s3=peg$FAILED;s3===peg$FAILED&&(peg$c76.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c77))),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c78(s1)),s0=s1,s0}function peg$parseisotope(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c43)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED&&(s4=null),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c79(s1)),s0=s1,s0}options=void 0===options?{}:options;var nOpenParentheses=input.split("(").length-1,nCloseParentheses=input.split(")").length-1;if(nOpenParentheses!==nCloseParentheses)throw peg$buildSimpleError("The number of opening parentheses does not match the number of closing parentheses.",0);var peg$FAILED={},peg$startRuleFunctions={chain:peg$parsechain},peg$startRuleFunction=peg$parsechain,peg$c0=function(s){for(var branches=[],rings=[],i=0;imax;){let prev=current;callback(prev),current=vertices[current].getNextInRing(vertices,this.id,previousVertexId),previousVertexId=prev,current==startVertexId&&(current=null),max++}}getOrderedNeighbours(ringConnections){let orderedNeighbours=Array(this.neighbours.length);for(let i=0,vertices;inewPathLength){var l,m,n;if(previousPathLength===newPathLength+1)for(pe_prime[i][j]=[pe[i][j].length],l=pe[i][j].length;l--;)for(pe_prime[i][j][l]=[pe[i][j][l].length],m=pe[i][j][l].length;m--;)for(pe_prime[i][j][l][m]=[pe[i][j][l][m].length],n=pe[i][j][l][m].length;n--;)pe_prime[i][j][l][m][n]=[pe[i][j][l][m][0],pe[i][j][l][m][1]];else pe_prime[i][j]=[];for(d[i][j]=newPathLength,pe[i][j]=[[]],l=pe[i][k][0].length;l--;)pe[i][j][0].push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)pe[i][j][0].push(pe[k][j][0][l])}else if(previousPathLength===newPathLength){if(pe[i][k].length&&pe[k][j].length){var l;if(pe[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j][0]=tmp}}}else if(previousPathLength===newPathLength-1){var l;if(pe_prime[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j][0]=tmp}}}return{d:d,pe:pe,pe_prime:pe_prime}}static getRingCandidates(d,pe,pe_prime){let length=d.length,candidates=[],c=0;for(let i=0;insssr)return cSssr}else for(let j=0,bonds;jnsssr)return cSssr}return cSssr}static getEdgeCount(adjacencyMatrix){let edgeCount=0,length=adjacencyMatrix.length;for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeCount++;return edgeCount}static getEdgeList(adjacencyMatrix){let length=adjacencyMatrix.length,edgeList=[];for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeList.push([i,j]);return edgeList}static bondsToAtoms(bonds){let atoms=new Set;for(var i=bonds.length;i--;)atoms.add(bonds[i][0]),atoms.add(bonds[i][1]);return atoms}static getBondCount(atoms,adjacencyMatrix){let count=0;for(let u of atoms)for(let v of atoms)u!==v&&(count+=adjacencyMatrix[u][v]);return count/2}static pathSetsContain(pathSets,pathSet,bonds,allBonds,arrBondCount,arrRingCount){for(var i=pathSets.length;i--;){if(SSSR.isSupersetOf(pathSet,pathSets[i]))return!0;if(pathSets[i].size===pathSet.size&&SSSR.areSetsEqual(pathSets[i],pathSet))return!0}let count=0,allContained=!1;for(i=bonds.length;i--;)for(var j=allBonds.length;j--;)(bonds[i][0]===allBonds[j][0]&&bonds[i][1]===allBonds[j][1]||bonds[i][1]===allBonds[j][0]&&bonds[i][0]===allBonds[j][1])&&count++,count===bonds.length&&(allContained=!0);let specialCase=!1;if(allContained)for(let element of pathSet)if(arrRingCount[element]e.vertexState=VertexState.VALUES.NOT_FOUND)}getSourceNode(){let ends=[];for(let index=0;indexthis._nodes[v].onRing=!0);continue}node.neighbours.forEach(neighbour=>{if(!path.some(e=>e===neighbour.neighbour)||neighbour.neighbour===start.id){let newPath=[...path];newPath.push(neighbour.neighbour),queue.push(newPath)}}),firstPass=!1}}sortByRingPreference(array){let sortedArray=[...array];return sortedArray.sort((a,b)=>this._nodes[a.neighbour].onRing===this._nodes[b.neighbour].onRing?a.direction>b.direction?-1:a.direction{let edges=graph.getEdges(vertex.id);for(var i=0;is.sideCount[1]||s.totalSideCount[0]>s.totalSideCount[1]){this.multiplyNormals(normals,opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB);line.shorten(opts.bondLength-opts.shortBondLength*opts.bondLength),svgWrapper.drawLine(line),svgWrapper.drawLine(new Line(a,b,elementA,elementB))}else if(s.sideCount[0]_Mathabs2(_MathPI3-angle)&&svgWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,vertex.value.chirality)}if(opts.debug)for(var i=0;i {\r\n const context = canvas.getContext('2d');\r\n context.clearRect(0, 0, canvas.width, canvas.height);\r\n })\r\n};\r\n\r\n/**\r\n* Parses the entered smiles string.\r\n*\r\n* @static\r\n* @param {String} smiles A SMILES string.\r\n* @param {Function} successCallback A callback that is called on success with the parse tree.\r\n* @param {Function} errorCallback A callback that is called with the error object on error.\r\n*/\r\nSmilesDrawer.parse = function(smiles, successCallback, errorCallback) {\r\n try {\r\n if (successCallback) {\r\n successCallback(Parser.parse(smiles));\r\n }\r\n } catch (err) {\r\n if (errorCallback) {\r\n errorCallback(err);\r\n }\r\n }\r\n};\r\n\r\nif (canUseDOM) {\r\n window.SmilesDrawer = SmilesDrawer;\r\n}\r\n\r\n// There be dragons (polyfills)\r\n\r\nif (!Array.prototype.fill) {\r\nObject.defineProperty(Array.prototype, 'fill', {\r\n value: function(value) {\r\n\r\n // Steps 1-2.\r\n if (this == null) {\r\n throw new TypeError('this is null or not defined');\r\n }\r\n\r\n var O = Object(this);\r\n\r\n // Steps 3-5.\r\n var len = O.length >>> 0;\r\n\r\n // Steps 6-7.\r\n var start = arguments[1];\r\n var relativeStart = start >> 0;\r\n\r\n // Step 8.\r\n var k = relativeStart < 0 ?\r\n Math.max(len + relativeStart, 0) :\r\n Math.min(relativeStart, len);\r\n\r\n // Steps 9-10.\r\n var end = arguments[2];\r\n var relativeEnd = end === undefined ?\r\n len : end >> 0;\r\n\r\n // Step 11.\r\n var final = relativeEnd < 0 ?\r\n Math.max(len + relativeEnd, 0) :\r\n Math.min(relativeEnd, len);\r\n\r\n // Step 12.\r\n while (k < final) {\r\n O[k] = value;\r\n k++;\r\n }\r\n\r\n // Step 13.\r\n return O;\r\n }\r\n});\r\n}\r\n\r\nmodule.exports = SmilesDrawer;","//@ts-check\r\n\r\n/** \r\n * A static class containing helper functions for array-related tasks. \r\n */\r\nclass ArrayHelper {\r\n /**\r\n * Clone an array or an object. If an object is passed, a shallow clone will be created.\r\n *\r\n * @static\r\n * @param {*} arr The array or object to be cloned.\r\n * @returns {*} A clone of the array or object.\r\n */\r\n static clone(arr) {\r\n let out = Array.isArray(arr) ? Array() : {};\r\n \r\n for (let key in arr) {\r\n let value = arr[key];\r\n \r\n if (typeof value.clone === 'function') {\r\n out[key] = value.clone();\r\n }\r\n else {\r\n out[key] = (typeof value === 'object') ? ArrayHelper.clone(value) : value;\r\n }\r\n }\r\n \r\n return out;\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not the two arrays contain the same elements.\r\n * Only supports 1d, non-nested arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not the two arrays contain the same elements.\r\n */\r\n static equals(arrA, arrB) {\r\n if (arrA.length !== arrB.length) {\r\n return false;\r\n }\r\n\r\n let tmpA = arrA.slice().sort();\r\n let tmpB = arrB.slice().sort();\r\n\r\n for (let i = 0; i < tmpA.length; i++) {\r\n if (tmpA[i] !== tmpB[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns a string representation of an array. If the array contains objects with an id property, the id property is printed for each of the elements.\r\n *\r\n * @static\r\n * @param {Object[]} arr An array.\r\n * @param {*} arr[].id If the array contains an object with the property 'id', the properties value is printed. Else, the array elements value is printend.\r\n * @returns {String} A string representation of the array.\r\n */\r\n static print(arr) {\r\n if (arr.length == 0) {\r\n return '';\r\n }\r\n\r\n let s = '(';\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n s += arr[i].id ? arr[i].id + ', ' : arr[i] + ', ';\r\n }\r\n\r\n s = s.substring(0, s.length - 2);\r\n\r\n return s + ')';\r\n }\r\n\r\n /**\r\n * Run a function for each element in the array. The element is supplied as an argument for the callback function\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Function} callback The callback function that is called for each element.\r\n */\r\n static each(arr, callback) {\r\n for (let i = 0; i < arr.length; i++) {\r\n callback(arr[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Return the array element from an array containing objects, where a property of the object is set to a given value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {(String|Number)} property A property contained within an object in the array.\r\n * @param {(String|Number)} value The value of the property.\r\n * @returns {*} The array element matching the value.\r\n */\r\n static get(arr, property, value) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][property] == value) {\r\n return arr[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains a given value. the options object passed as a second argument can contain three properties. value: The value to be searched for. property: The property that is to be searched for a given value. func: A function that is used as a callback to return either true or false in order to do a custom comparison.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Object} options See method description.\r\n * @param {*} options.value The value for which to check.\r\n * @param {String} [options.property=undefined] The property on which to check.\r\n * @param {Function} [options.func=undefined] A custom property function.\r\n * @returns {Boolean} A boolean whether or not the array contains a value.\r\n */\r\n static contains(arr, options) {\r\n if (!options.property && !options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] == options.value) {\r\n return true;\r\n }\r\n }\r\n } else if (options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (options.func(arr[i])) {\r\n return true;\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][options.property] == options.value) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array containing the intersection between two arrays. That is, values that are common to both arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The intersecting vlaues.\r\n */\r\n static intersection(arrA, arrB) {\r\n let intersection = [];\r\n \r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n intersection.push(arrA[i]);\r\n }\r\n }\r\n }\r\n\r\n return intersection;\r\n }\r\n\r\n /**\r\n * Returns an array of unique elements contained in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @returns {Array} An array of unique elements contained within the array supplied as an argument.\r\n */\r\n static unique(arr) {\r\n let contains = {};\r\n return arr.filter(function (i) {\r\n // using !== instead of hasOwnProperty (http://andrew.hedges.name/experiments/in/)\r\n return contains[i] !== undefined ? false : (contains[i] = true);\r\n });\r\n }\r\n\r\n /**\r\n * Count the number of occurences of a value in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be counted.\r\n * @returns {Number} The number of occurences of a value in the array.\r\n */\r\n static count(arr, value) {\r\n let count = 0;\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] === value) {\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Toggles the value of an array. If a value is not contained in an array, the array returned will contain all the values of the original array including the value. If a value is contained in an array, the array returned will contain all the values of the original array excluding the value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be toggled.\r\n * @returns {Array} The toggled array.\r\n */\r\n static toggle(arr, value) {\r\n let newArr = Array();\r\n\r\n let removed = false;\r\n for (let i = 0; i < arr.length; i++) {\r\n // Do not copy value if it exists\r\n if (arr[i] !== value) {\r\n newArr.push(arr[i]);\r\n } else {\r\n // The element was not copied to the new array, which\r\n // means it was removed\r\n removed = true;\r\n }\r\n }\r\n\r\n // If the element was not removed, then it was not in the array\r\n // so add it\r\n if (!removed) {\r\n newArr.push(value);\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n /**\r\n * Remove a value from an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} A new array with the element with a given value removed.\r\n */\r\n static remove(arr, value) {\r\n let tmp = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] !== value) {\r\n tmp.push(arr[i]);\r\n }\r\n }\r\n\r\n return tmp;\r\n }\r\n\r\n /**\r\n * Remove a value from an array with unique values.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} An array with the element with a given value removed.\r\n */\r\n static removeUnique(arr, value) {\r\n let index = arr.indexOf(value);\r\n\r\n if (index > -1) {\r\n arr.splice(index, 1);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Remove all elements contained in one array from another array.\r\n *\r\n * @static\r\n * @param {Array} arrA The array to be filtered.\r\n * @param {Array} arrB The array containing elements that will be removed from the other array.\r\n * @returns {Array} The filtered array.\r\n */\r\n static removeAll(arrA, arrB) {\r\n return arrA.filter(function (item) {\r\n return arrB.indexOf(item) === -1;\r\n });\r\n }\r\n\r\n /**\r\n * Merges two arrays and returns the result. The first array will be appended to the second array.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The merged array.\r\n */\r\n static merge(arrA, arrB) {\r\n let arr = new Array(arrA.length + arrB.length);\r\n\r\n for (let i = 0; i < arrA.length; i++) {\r\n arr[i] = arrA[i];\r\n }\r\n\r\n for (let i = 0; i < arrB.length; i++) {\r\n arr[arrA.length + i] = arrB[i];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains all the elements of another array, without regard to the order.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not both array contain the same elements.\r\n */\r\n static containsAll(arrA, arrB) {\r\n let containing = 0;\r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n containing++;\r\n }\r\n }\r\n }\r\n\r\n return containing === arrB.length;\r\n }\r\n \r\n /**\r\n * Sort an array of atomic number information. Where the number is indicated as x, x.y, x.y.z, ...\r\n *\r\n * @param {Object[]} arr An array of vertex ids with their associated atomic numbers.\r\n * @param {Number} arr[].vertexId A vertex id.\r\n * @param {String} arr[].atomicNumber The atomic number associated with the vertex id.\r\n * @returns {Object[]} The array sorted by atomic number. Example of an array entry: { atomicNumber: 2, vertexId: 5 }.\r\n */\r\n static sortByAtomicNumberDesc(arr) {\r\n let map = arr.map(function(e, i) {\r\n return { index: i, value: e.atomicNumber.split('.').map(Number) };\r\n });\r\n\r\n map.sort(function(a, b) {\r\n let min = Math.min(b.value.length, a.value.length);\r\n let i = 0;\r\n \r\n while(i < min && b.value[i] === a.value[i]) {\r\n i++;\r\n }\r\n\r\n return i === min ? b.value.length - a.value.length : b.value[i] - a.value[i];\r\n });\r\n\r\n return map.map(function(e) {\r\n return arr[e.index];\r\n });\r\n }\r\n\r\n /**\r\n * Copies a an n-dimensional array.\r\n * \r\n * @param {Array} arr The array to be copied.\r\n * @returns {Array} The copy.\r\n */\r\n static deepCopy(arr) {\r\n let newArr = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n let item = arr[i];\r\n\r\n if (item instanceof Array) {\r\n newArr[i] = ArrayHelper.deepCopy(item);\r\n } else {\r\n newArr[i] = item;\r\n }\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = ArrayHelper;","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper');\r\n\r\n/** \r\n * A class representing an atom.\r\n * \r\n * @property {String} element The element symbol of this atom. Single-letter symbols are always uppercase. Examples: H, C, F, Br, Si, ...\r\n * @property {Boolean} drawExplicit A boolean indicating whether or not this atom is drawn explicitly (for example, a carbon atom). This overrides the default behaviour.\r\n * @property {Object[]} ringbonds An array containing the ringbond ids and bond types as specified in the original SMILE.\r\n * @property {String} branchBond The branch bond as defined in the SMILES.\r\n * @property {Number} ringbonds[].id The ringbond id as defined in the SMILES.\r\n * @property {String} ringbonds[].bondType The bond type of the ringbond as defined in the SMILES.\r\n * @property {Number[]} rings The ids of rings which contain this atom.\r\n * @property {String} bondType The bond type associated with this array. Examples: -, =, #, ...\r\n * @property {Boolean} isBridge A boolean indicating whether or not this atom is part of a bridge in a bridged ring (contained by the largest ring).\r\n * @property {Boolean} isBridgeNode A boolean indicating whether or not this atom is a bridge node (a member of the largest ring in a bridged ring which is connected to a bridge-atom).\r\n * @property {Number[]} originalRings Used to back up rings when they are replaced by a bridged ring.\r\n * @property {Number} bridgedRing The id of the bridged ring if the atom is part of a bridged ring.\r\n * @property {Number[]} anchoredRings The ids of the rings that are anchored to this atom. The centers of anchored rings are translated when this atom is translated.\r\n * @property {Object} bracket If this atom is defined as a bracket atom in the original SMILES, this object contains all the bracket information. Example: { hcount: {Number}, charge: ['--', '-', '+', '++'], isotope: {Number} }.\r\n * @property {Number} plane Specifies on which \"plane\" the atoms is in stereochemical deptictions (-1 back, 0 middle, 1 front).\r\n * @property {Object[]} attachedPseudoElements A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @property {String} attachedPseudoElement[].element The element symbol.\r\n * @property {Number} attachedPseudoElement[].count The number of occurences that match the key.\r\n * @property {Number} attachedPseudoElement[].hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n * @property {Boolean} hasAttachedPseudoElements A boolean indicating whether or not this attom will be drawn with an attached pseudo element or concatinated elements.\r\n * @property {Boolean} isDrawn A boolean indicating whether or not this atom is drawn. In contrast to drawExplicit, the bond is drawn neither.\r\n * @property {Boolean} isConnectedToRing A boolean indicating whether or not this atom is directly connected (but not a member of) a ring.\r\n * @property {String[]} neighbouringElements An array containing the element symbols of neighbouring atoms.\r\n * @property {Boolean} isPartOfAromaticRing A boolean indicating whether or not this atom is part of an explicitly defined aromatic ring. Example: c1ccccc1.\r\n * @property {Number} bondCount The number of bonds in which this atom is participating.\r\n * @property {String} chirality The chirality of this atom if it is a stereocenter (R or S).\r\n * @property {Number} priority The priority of this atom acording to the CIP rules, where 0 is the highest priority.\r\n * @property {Boolean} mainChain A boolean indicating whether or not this atom is part of the main chain (used for chirality).\r\n * @property {String} hydrogenDirection The direction of the hydrogen, either up or down. Only for stereocenters with and explicit hydrogen.\r\n * @property {Number} subtreeDepth The depth of the subtree coming from a stereocenter.\r\n */\r\nclass Atom {\r\n /**\r\n * The constructor of the class Atom.\r\n *\r\n * @param {String} element The one-letter code of the element.\r\n * @param {String} [bondType='-'] The type of the bond associated with this atom.\r\n */\r\n constructor(element, bondType = '-') {\r\n this.element = element.length === 1 ? element.toUpperCase() : element;\r\n this.drawExplicit = false;\r\n this.ringbonds = Array();\r\n this.rings = Array();\r\n this.bondType = bondType;\r\n this.branchBond = null;\r\n this.isBridge = false;\r\n this.isBridgeNode = false;\r\n this.originalRings = Array();\r\n this.bridgedRing = null;\r\n this.anchoredRings = Array();\r\n this.bracket = null;\r\n this.plane = 0;\r\n this.attachedPseudoElements = {};\r\n this.hasAttachedPseudoElements = false;\r\n this.isDrawn = true;\r\n this.isConnectedToRing = false;\r\n this.neighbouringElements = Array();\r\n this.isPartOfAromaticRing = element !== this.element;\r\n this.bondCount = 0;\r\n this.chirality = '';\r\n this.isStereoCenter = false;\r\n this.priority = 0;\r\n this.mainChain = false;\r\n this.hydrogenDirection = 'down';\r\n this.subtreeDepth = 1;\r\n this.hasHydrogen = false;\r\n }\r\n\r\n /**\r\n * Adds a neighbouring element to this atom.\r\n * \r\n * @param {String} element A string representing an element.\r\n */\r\n addNeighbouringElement(element) {\r\n this.neighbouringElements.push(element);\r\n }\r\n\r\n /**\r\n * Attaches a pseudo element (e.g. Ac) to the atom.\r\n * @param {String} element The element identifier (e.g. Br, C, ...).\r\n * @param {String} previousElement The element that is part of the main chain (not the terminals that are converted to the pseudo element or concatinated).\r\n * @param {Number} [hydrogenCount=0] The number of hydrogens for the element.\r\n * @param {Number} [charge=0] The charge for the element.\r\n */\r\n attachPseudoElement(element, previousElement, hydrogenCount = 0, charge = 0) {\r\n if (hydrogenCount === null) {\r\n hydrogenCount = 0;\r\n }\r\n\r\n if (charge === null) {\r\n charge = 0;\r\n }\r\n\r\n let key = hydrogenCount + element + charge;\r\n\r\n if (this.attachedPseudoElements[key]) {\r\n this.attachedPseudoElements[key].count += 1;\r\n } else {\r\n this.attachedPseudoElements[key] = {\r\n element: element,\r\n count: 1,\r\n hydrogenCount: hydrogenCount,\r\n previousElement: previousElement,\r\n charge: charge\r\n };\r\n }\r\n\r\n this.hasAttachedPseudoElements = true;\r\n }\r\n\r\n /**\r\n * Returns the attached pseudo elements sorted by hydrogen count (ascending).\r\n *\r\n * @returns {Object} The sorted attached pseudo elements.\r\n */\r\n getAttachedPseudoElements() {\r\n let ordered = {};\r\n let that = this;\r\n\r\n Object.keys(this.attachedPseudoElements).sort().forEach(function (key) {\r\n ordered[key] = that.attachedPseudoElements[key];\r\n });\r\n\r\n return ordered;\r\n }\r\n\r\n /**\r\n * Returns the number of attached pseudo elements.\r\n *\r\n * @returns {Number} The number of attached pseudo elements.\r\n */\r\n getAttachedPseudoElementsCount() {\r\n return Object.keys(this.attachedPseudoElements).length;\r\n }\r\n\r\n /**\r\n * Returns whether this atom is a heteroatom (not C and not H).\r\n *\r\n * @returns {Boolean} A boolean indicating whether this atom is a heteroatom.\r\n */\r\n isHeteroAtom() {\r\n return this.element !== 'C' && this.element !== 'H';\r\n }\r\n\r\n /**\r\n * Defines this atom as the anchor for a ring. When doing repositionings of the vertices and the vertex associated with this atom is moved, the center of this ring is moved as well.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n addAnchoredRing(ringId) {\r\n if (!ArrayHelper.contains(this.anchoredRings, {\r\n value: ringId\r\n })) {\r\n this.anchoredRings.push(ringId);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of ringbonds (breaks in rings to generate the MST of the smiles) within this atom is connected to.\r\n *\r\n * @returns {Number} The number of ringbonds this atom is connected to.\r\n */\r\n getRingbondCount() {\r\n return this.ringbonds.length;\r\n }\r\n\r\n /**\r\n * Backs up the current rings.\r\n */\r\n backupRings() {\r\n this.originalRings = Array(this.rings.length);\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings[i] = this.rings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recent backed up rings.\r\n */\r\n restoreRings() {\r\n this.rings = Array(this.originalRings.length);\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings[i] = this.originalRings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not two atoms share a common ringbond id. A ringbond is a break in a ring created when generating the spanning tree of a structure.\r\n *\r\n * @param {Atom} atomA An atom.\r\n * @param {Atom} atomB An atom.\r\n * @returns {Boolean} A boolean indicating whether or not two atoms share a common ringbond.\r\n */\r\n haveCommonRingbond(atomA, atomB) {\r\n for (let i = 0; i < atomA.ringbonds.length; i++) {\r\n for (let j = 0; j < atomB.ringbonds.length; j++) {\r\n if (atomA.ringbonds[i].id == atomB.ringbonds[j].id) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not the neighbouring elements of this atom equal the supplied array.\r\n * \r\n * @param {String[]} arr An array containing all the elements that are neighbouring this atom. E.g. ['C', 'O', 'O', 'N']\r\n * @returns {Boolean} A boolean indicating whether or not the neighbours match the supplied array of elements.\r\n */\r\n neighbouringElementsEqual(arr) {\r\n if (arr.length !== this.neighbouringElements.length) {\r\n return false;\r\n }\r\n\r\n arr.sort();\r\n this.neighbouringElements.sort();\r\n\r\n for (var i = 0; i < this.neighbouringElements.length; i++) {\r\n if (arr[i] !== this.neighbouringElements[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the atomic number of this atom.\r\n * \r\n * @returns {Number} The atomic number of this atom.\r\n */\r\n getAtomicNumber() {\r\n return Atom.atomicNumbers[this.element];\r\n }\r\n\r\n /**\r\n * Get the maximum number of bonds for this atom.\r\n * \r\n * @returns {Number} The maximum number of bonds of this atom.\r\n */\r\n getMaxBonds() {\r\n return Atom.maxBonds[this.element];\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to their maximum bonds.\r\n */\r\n static get maxBonds() {\r\n return {\r\n 'H': 1,\r\n 'C': 4,\r\n 'N': 3,\r\n 'O': 2,\r\n 'P': 3,\r\n 'S': 2,\r\n 'B': 3,\r\n 'F': 1,\r\n 'I': 1,\r\n 'Cl': 1,\r\n 'Br': 1\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic number.\r\n */\r\n static get atomicNumbers() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic mass.\r\n */\r\n static get mass() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n}\r\n\r\nmodule.exports = Atom;","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Ring = require('./Ring');\r\nconst { getChargeText } = require('./UtilityFunctions');\r\n\r\n/** \r\n * A class wrapping a canvas element.\r\n * \r\n * @property {HTMLElement} canvas The HTML element for the canvas associated with this CanvasWrapper instance.\r\n * @property {CanvasRenderingContext2D} ctx The CanvasRenderingContext2D of the canvas associated with this CanvasWrapper instance.\r\n * @property {Object} colors The colors object as defined in the SmilesDrawer options.\r\n * @property {Object} opts The SmilesDrawer options.\r\n * @property {Number} drawingWidth The width of the canvas.\r\n * @property {Number} drawingHeight The height of the canvas.\r\n * @property {Number} realWidth The width of the canvas real.\r\n * @property {Number} realHeight The height of the canvas real.\r\n * @property {Number} offsetX The horizontal offset required for centering the drawing.\r\n * @property {Number} offsetY The vertical offset required for centering the drawing.\r\n * @property {Number} fontLarge The large font size in pt.\r\n * @property {Number} fontSmall The small font size in pt.\r\n */\r\nclass CanvasWrapper {\r\n /**\r\n * The constructor for the class CanvasWrapper.\r\n *\r\n * @param {(String|HTMLElement)} target The canvas id or the canvas HTMLElement.\r\n * @param {ThemeManager} themeManager Theme manager for setting proper colors.\r\n * @param {Object} options The smiles drawer options object.\r\n */\r\n constructor(target, themeManager, options) {\r\n if (typeof target === 'string' || target instanceof String) {\r\n this.canvas = document.getElementById(target);\r\n } else {\r\n this.canvas = target;\r\n }\r\n\r\n this.ctx = this.canvas.getContext('2d');\r\n this.themeManager = themeManager;\r\n this.opts = options;\r\n this.drawingWidth = 0.0;\r\n this.drawingHeight = 0.0;\r\n this.realWidth = 0.0;\r\n this.realHeight = 0.0;\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n this.fontLarge = this.opts.fontSizeLarge + 'pt Helvetica, Arial, sans-serif';\r\n this.fontSmall = this.opts.fontSizeSmall + 'pt Helvetica, Arial, sans-serif';\r\n\r\n this.updateSize(this.opts.width, this.opts.height);\r\n\r\n this.ctx.font = this.fontLarge;\r\n this.hydrogenWidth = this.ctx.measureText('H').width;\r\n this.halfHydrogenWidth = this.hydrogenWidth / 2.0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // TODO: Find out why clear was here.\r\n // this.clear();\r\n }\r\n\r\n /**\r\n * Update the width and height of the canvas\r\n * \r\n * @param {Number} width \r\n * @param {Number} height \r\n */\r\n updateSize(width, height) {\r\n this.devicePixelRatio = window.devicePixelRatio || 1;\r\n this.backingStoreRatio = this.ctx.webkitBackingStorePixelRatio || this.ctx.mozBackingStorePixelRatio ||\r\n this.ctx.msBackingStorePixelRatio || this.ctx.oBackingStorePixelRatio ||\r\n this.ctx.backingStorePixelRatio || 1;\r\n this.ratio = this.devicePixelRatio / this.backingStoreRatio;\r\n\r\n this.canvas.width = width * this.ratio;\r\n this.canvas.height = height * this.ratio;\r\n if (this.ratio !== 1) {\r\n this.realWidth = width;\r\n this.realHeight = height;\r\n this.canvas.style.width = width + 'px';\r\n this.canvas.style.height = height + 'px';\r\n this.ctx.setTransform(this.ratio, 0, 0, this.ratio, 0, 0);\r\n }\r\n }\r\n\r\n /**\r\n * Sets a provided theme.\r\n *\r\n * @param {Object} theme A theme from the smiles drawer options.\r\n */\r\n setTheme(theme) {\r\n this.colors = theme;\r\n }\r\n\r\n /**\r\n * Scale the canvas based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n scale(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n var padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n var scaleX = this.canvas.offsetWidth / this.drawingWidth;\r\n var scaleY = this.canvas.offsetHeight / this.drawingHeight;\r\n\r\n var scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n\r\n this.ctx.scale(scale, scale);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.canvas.offsetHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.canvas.offsetWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Resets the transform of the canvas.\r\n */\r\n reset() {\r\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.colors) {\r\n return this.colors[key];\r\n }\r\n\r\n return this.colors['C'];\r\n }\r\n\r\n /**\r\n * Draws a circle to a canvas context.\r\n * @param {Number} x The x coordinate of the circles center.\r\n * @param {Number} y The y coordinate of the circles center.\r\n * @param {Number} radius The radius of the circle\r\n * @param {String} color A hex encoded color.\r\n * @param {Boolean} [fill=true] Whether to fill or stroke the circle.\r\n * @param {Boolean} [debug=false] Draw in debug mode.\r\n * @param {String} [debugText=''] A debug message.\r\n */\r\n drawCircle(x, y, radius, color, fill = true, debug = false, debugText = '') {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.lineWidth = 1.5;\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, radius, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n\r\n if (debug) {\r\n if (fill) {\r\n ctx.fillStyle = '#f00';\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = '#f00';\r\n ctx.stroke();\r\n }\r\n\r\n this.drawDebugText(x, y, debugText);\r\n } else {\r\n if (fill) {\r\n ctx.fillStyle = color;\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = color;\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a line to a canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} [dashed=false] Whether or not the line is dashed.\r\n * @param {Number} [alpha=1.0] The alpha value of the color.\r\n */\r\n drawLine(line, dashed = false, alpha = 1.0) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(4.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n // Draw the \"shadow\"\r\n if (!dashed) {\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness + 1.2;\r\n ctx.strokeStyle = this.themeManager.getColor('BACKGROUND');\r\n ctx.stroke();\r\n ctx.globalCompositeOperation = 'source-over';\r\n ctx.restore();\r\n }\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n\r\n let gradient = this.ctx.createLinearGradient(l.x, l.y, r.x, r.y);\r\n if (line.isDecayPoint) {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(\"DECAY\"));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(\"DECAY\"));\r\n } else {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n }\r\n\r\n if (dashed) {\r\n ctx.setLineDash([1, 1.5]);\r\n ctx.lineWidth = this.opts.bondThickness / 1.5;\r\n }\r\n\r\n if (alpha < 1.0) {\r\n ctx.globalAlpha = alpha;\r\n }\r\n\r\n ctx.strokeStyle = gradient;\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Number} width The wedge width.\r\n */\r\n drawWedge(line, width = 1.0) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(5.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l;\r\n let end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness));\r\n let u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness));\r\n let v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness));\r\n let w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(t.x, t.y);\r\n ctx.lineTo(u.x, u.y);\r\n ctx.lineTo(v.x, v.y);\r\n ctx.lineTo(w.x, w.y);\r\n\r\n let gradient = this.ctx.createRadialGradient(r.x, r.y, this.opts.bondLength, r.x, r.y, 0);\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n let l = line.getLeftVector().clone();\r\n let r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start;\r\n let end;\r\n let sStart;\r\n let sEnd;\r\n\r\n let shortLine = line.clone();\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n\r\n shortLine.shortenRight(1.0);\r\n\r\n sStart = shortLine.getRightVector().clone();\r\n sEnd = shortLine.getLeftVector().clone();\r\n } else {\r\n start = l;\r\n end = r;\r\n\r\n shortLine.shortenLeft(1.0);\r\n\r\n sStart = shortLine.getLeftVector().clone();\r\n sEnd = shortLine.getRightVector().clone();\r\n }\r\n\r\n sStart.x += offsetX;\r\n sStart.y += offsetY;\r\n sEnd.x += offsetX;\r\n sEnd.y += offsetY;\r\n\r\n let dir = Vector2.subtract(end, start).normalize();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n let length = line.getLength();\r\n let step = 1.25 / (length / (this.opts.bondThickness * 3.0));\r\n\r\n let changed = false;\r\n for (var t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length);\r\n let startDash = Vector2.add(start, to);\r\n let width = 1.5 * t;\r\n let dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n if (!changed && t > 0.5) {\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.strokeStyle = this.themeManager.getColor(line.getRightElement()) || this.themeManager.getColor('C');\r\n changed = true;\r\n }\r\n \r\n startDash.subtract(dashOffset);\r\n ctx.moveTo(startDash.x, startDash.y);\r\n startDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n ctx.lineTo(startDash.x, startDash.y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.font = '5px Droid Sans, sans-serif';\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'top';\r\n ctx.fillStyle = '#ff0000';\r\n ctx.fillText(text, x + this.offsetX, y + this.offsetY);\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a ball to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, this.opts.bondLength / 4.5, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a point to the canvas.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, 1.5, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, 0.75, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'alphabetic';\r\n\r\n // Charge\r\n let chargeText = '';\r\n let chargeWidth = 0;\r\n\r\n if (charge) {\r\n chargeText = getChargeText(charge);\r\n\r\n ctx.font = this.fontSmall;\r\n chargeWidth = ctx.measureText(chargeText).width;\r\n }\r\n\r\n let isotopeText = '0';\r\n let isotopeWidth = 0;\r\n\r\n if (isotope > 0) {\r\n isotopeText = isotope.toString();\r\n ctx.font = this.fontSmall;\r\n isotopeWidth = ctx.measureText(isotopeText).width;\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') && \r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = { '0O': { element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: '' } };\r\n charge = 0;\r\n }\r\n\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillStyle = this.themeManager.getColor('BACKGROUND');\r\n\r\n let dim = ctx.measureText(elementName);\r\n\r\n dim.totalWidth = dim.width + chargeWidth;\r\n dim.height = parseInt(this.fontLarge, 10);\r\n\r\n let r = (dim.width > this.opts.fontSizeLarge) ? dim.width : this.opts.fontSizeLarge;\r\n r /= 1.5;\r\n\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, r, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n let cursorPos = -dim.width / 2.0;\r\n let cursorPosLeft = -dim.width / 2.0;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fillText(elementName, x + offsetX + cursorPos, y + this.opts.halfFontSizeLarge + offsetY);\r\n cursorPos += dim.width;\r\n\r\n if (charge) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(chargeText, x + offsetX + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += chargeWidth;\r\n }\r\n\r\n if (isotope > 0) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(isotopeText, x + offsetX + cursorPosLeft - isotopeWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPosLeft -= isotopeWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hydrogenWidth = 0;\r\n let hydrogenCountWidth = 0;\r\n\r\n if (hydrogens === 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n cursorPosLeft -= hydrogenWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.fillText('H', hx, hy);\r\n\r\n cursorPos += hydrogenWidth;\r\n } else if (hydrogens > 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n ctx.font = this.fontSmall;\r\n hydrogenCountWidth = ctx.measureText(hydrogens).width;\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillText('H', hx, hy);\r\n\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogens, hx + this.halfHydrogenWidth + hydrogenCountWidth, hy + this.opts.fifthFontSizeSmall);\r\n\r\n cursorPos += hydrogenWidth + this.halfHydrogenWidth + hydrogenCountWidth;\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let openParenthesisWidth = 0;\r\n let closeParenthesisWidth = 0;\r\n\r\n let element = attachedPseudoElement[key].element;\r\n let elementCount = attachedPseudoElement[key].count;\r\n let hydrogenCount = attachedPseudoElement[key].hydrogenCount;\r\n let elementCharge = attachedPseudoElement[key].charge;\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n openParenthesisWidth = ctx.measureText('(').width;\r\n closeParenthesisWidth = ctx.measureText(')').width;\r\n }\r\n\r\n let elementWidth = ctx.measureText(element).width;\r\n let elementCountWidth = 0;\r\n\r\n let elementChargeText = '';\r\n let elementChargeWidth = 0;\r\n\r\n hydrogenWidth = 0;\r\n\r\n if (hydrogenCount > 0) {\r\n hydrogenWidth = this.hydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n elementCountWidth = ctx.measureText(elementCount).width;\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n elementChargeText = getChargeText(elementCharge);\r\n elementChargeWidth = ctx.measureText(elementChargeText).width;\r\n }\r\n\r\n hydrogenCountWidth = 0;\r\n\r\n if (hydrogenCount > 1) {\r\n hydrogenCountWidth = ctx.measureText(hydrogenCount).width;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(element);\r\n\r\n if (elementCount > 0) {\r\n cursorPosLeft -= elementCountWidth;\r\n }\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= closeParenthesisWidth;\r\n ctx.fillText(')', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText('(', hx + cursorPos, hy);\r\n cursorPos += openParenthesisWidth;\r\n }\r\n }\r\n\r\n if (direction === 'left') {\r\n cursorPosLeft -= elementWidth;\r\n ctx.fillText(element, hx + cursorPosLeft, hy)\r\n } else {\r\n ctx.fillText(element, hx + cursorPos, hy);\r\n cursorPos += elementWidth;\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n ctx.fillText('H', hx + cursorPosLeft, hy);\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPosLeft + hydrogenWidth, hy + this.opts.fifthFontSizeSmall);\r\n }\r\n } else {\r\n ctx.fillText('H', hx + cursorPos, hy);\r\n cursorPos += hydrogenWidth;\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += hydrogenCountWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= openParenthesisWidth;\r\n ctx.fillText('(', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText(')', hx + cursorPos, hy);\r\n cursorPos += closeParenthesisWidth;\r\n }\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementCount, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, hy + this.opts.fifthFontSizeSmall);\r\n } else {\r\n ctx.fillText(elementCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += elementCountWidth;\r\n }\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementChargeText, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n } else {\r\n ctx.fillText(elementChargeText, hx + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += elementChargeWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\n getChargeText(charge) {\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Draws a dubug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n this.drawCircle(x, y, 2, color, true, true, debugText);\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Clear the canvas.\r\n *\r\n */\r\n clear() {\r\n this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = CanvasWrapper;","//@ts-check\r\n\r\nclass DecayPoint {\r\n\r\n /**\r\n * Enum values for Decay points\r\n * ALL use all variants of decay points\r\n * COO -CO-O- type of decay\r\n * CONH -CO-NH- type of decay\r\n * @return {{ALL: number, COO: number, CONH: number}}\r\n */\r\n static get VALUES() {\r\n return { ALL: 0, COO: 1, CONH: 2 };\r\n }\r\n}\r\n\r\nmodule.exports = DecayPoint;\r\n","//@ts-check\r\n\r\nclass DecayState {\r\n\r\n static get VALUES() {\r\n return { NO: 0, STANDARD: 1, SOURCE: 2, STANDARD_AND_SOURCE: 3};\r\n }\r\n}\r\n\r\nmodule.exports = DecayState;\r\n","\r\nclass Direction {\r\n\r\n static get VALUES() {\r\n return { N: 0, POLYKETIDE: 1, C: 2 };\r\n }\r\n\r\n static getProperValue(isPolyketide, vertexElement, vertexId, firstVertexId) {\r\n if (isPolyketide) {\r\n return this.VALUES.POLYKETIDE;\r\n }\r\n if (vertexElement === \"C\" && vertexId !== firstVertexId) {\r\n return this.VALUES.C;\r\n }\r\n return this.VALUES.N;\r\n }\r\n\r\n}\r\n\r\nmodule.exports= Direction;\r\n","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Atom = require('./Atom');\r\nconst Ring = require('./Ring');\r\nconst RingConnection = require('./RingConnection');\r\nconst CanvasWrapper = require('./CanvasWrapper');\r\nconst Graph = require('./Graph');\r\nconst SSSR = require('./SSSR');\r\nconst DecayState = require('./DecayState');\r\nconst ThemeManager = require('./ThemeManager');\r\n\r\n/**\r\n * The main class of the application representing the smiles drawer\r\n *\r\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\r\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\r\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} totalOverlapScore The current internal total overlap score.\r\n * @property {Object} defaultOptions The default options.\r\n * @property {Object} opts The merged options.\r\n * @property {Object} theme The current theme.\r\n */\r\nclass Drawer {\r\n /**\r\n * The constructor for the class SmilesDrawer.\r\n *\r\n * @param {Object} options An object containing custom values for different options. It is merged with the default options.\r\n */\r\n constructor(options) {\r\n this.graph = null;\r\n this.doubleBondConfigCount = 0;\r\n this.doubleBondConfig = null;\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n this.canvasWrapper = null;\r\n this.totalOverlapScore = 0;\r\n\r\n this.defaultOptions = {\r\n width: 500,\r\n height: 500,\r\n offsetX: 0, /* offsetX offset of canvas in page X. Typically canvas.offsetLeft */\r\n offsetY: 0, /* offsetY offset of canvas in page Y. Typically canvas.offsetTop */\r\n bondThickness: 0.6,\r\n bondLength: 15,\r\n shortBondLength: 0.85,\r\n bondSpacing: 0.18 * 15,\r\n atomVisualization: 'default',\r\n isomeric: true,\r\n debug: false,\r\n terminalCarbons: false,\r\n explicitHydrogens: false,\r\n overlapSensitivity: 0.42,\r\n overlapResolutionIterations: 1,\r\n compactDrawing: true,\r\n fontSizeLarge: 5,\r\n fontSizeSmall: 3,\r\n padding: 20.0,\r\n experimentalSSSR: false,\r\n kkThreshold: 0.1,\r\n kkInnerThreshold: 0.1,\r\n kkMaxIteration: 20000,\r\n kkMaxInnerIteration: 50,\r\n kkMaxEnergy: 1e9,\r\n drawDecayPoints: DecayState.VALUES.NO,\r\n decaySource: [],\r\n mouseTolerance: 3,\r\n themes: {\r\n dark: {\r\n C: '#fff',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#fff',\r\n BACKGROUND: '#141414',\r\n DECAY: '#027c21'\r\n },\r\n light: {\r\n C: '#222',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#222',\r\n BACKGROUND: '#fff',\r\n DECAY: '#027c21'\r\n }\r\n }\r\n };\r\n\r\n this.opts = this.extend(true, this.defaultOptions, options);\r\n this.opts.halfBondSpacing = this.opts.bondSpacing / 2.0;\r\n this.opts.bondLengthSq = this.opts.bondLength * this.opts.bondLength;\r\n this.opts.halfFontSizeLarge = this.opts.fontSizeLarge / 2.0;\r\n this.opts.quarterFontSizeLarge = this.opts.fontSizeLarge / 4.0;\r\n this.opts.fifthFontSizeSmall = this.opts.fontSizeSmall / 5.0;\r\n\r\n // Set the default theme.\r\n this.theme = this.opts.themes.dark;\r\n\r\n this.drawDecayPoints = this.opts.drawDecayPoints;\r\n }\r\n\r\n /**\r\n * A helper method to extend the default options with user supplied ones.\r\n */\r\n extend() {\r\n let that = this;\r\n let extended = {};\r\n let deep = false;\r\n let i = 0;\r\n let length = arguments.length;\r\n\r\n if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {\r\n deep = arguments[0];\r\n i++;\r\n }\r\n\r\n let merge = function (obj) {\r\n for (var prop in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, prop)) {\r\n if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\r\n extended[prop] = that.extend(true, extended[prop], obj[prop]);\r\n } else {\r\n extended[prop] = obj[prop];\r\n }\r\n }\r\n }\r\n };\r\n\r\n for (; i < length; i++) {\r\n let obj = arguments[i];\r\n merge(obj);\r\n }\r\n\r\n return extended;\r\n }\r\n\r\n /**\r\n * Is setup to draw decay points?\r\n * when boolean this.drawDecayPoint is true then return isDecay\r\n * @param isDecay bool - edge.isDecay\r\n * @returns {Boolean}\r\n */\r\n isDrawDecayPoint(isDecay) {\r\n return this.drawDecayPoints !== DecayState.VALUES.NO && isDecay;\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to a canvas element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n this.initDraw(data, themeName, infoOnly);\r\n\r\n if (!this.infoOnly) {\r\n this.themeManager = new ThemeManager(this.opts.themes, themeName);\r\n this.canvasWrapper = new CanvasWrapper(target, this.themeManager, this.opts);\r\n }\r\n\r\n if (!infoOnly) {\r\n this.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n\r\n if (this.opts.debug) {\r\n console.log(this.graph);\r\n console.log(this.rings);\r\n console.log(this.ringConnections);\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n if (this.canvasWrapper) {\r\n this.canvasWrapper.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of rings this edge is a part of.\r\n *\r\n * @param {Number} edgeId The id of an edge.\r\n * @returns {Number} The number of rings the provided edge is part of.\r\n */\r\n edgeRingCount(edgeId) {\r\n let edge = this.graph.edges[edgeId];\r\n let a = this.graph.vertices[edge.sourceId];\r\n let b = this.graph.vertices[edge.targetId];\r\n\r\n return Math.min(a.value.rings.length, b.value.rings.length);\r\n }\r\n\r\n /**\r\n * Returns an array containing the bridged rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all bridged rings associated with this molecule.\r\n */\r\n getBridgedRings() {\r\n let bridgedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n bridgedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return bridgedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all fused rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all fused rings associated with this molecule.\r\n */\r\n getFusedRings() {\r\n let fusedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isFused) {\r\n fusedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return fusedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all spiros associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all spiros associated with this molecule.\r\n */\r\n getSpiros() {\r\n let spiros = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isSpiro) {\r\n spiros.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return spiros;\r\n }\r\n\r\n /**\r\n * Returns a string containing a semicolon and new-line separated list of ring properties: Id; Members Count; Neighbours Count; IsSpiro; IsFused; IsBridged; Ring Count (subrings of bridged rings)\r\n *\r\n * @returns {String} A string as described in the method description.\r\n */\r\n printRingInfo() {\r\n let result = '';\r\n for (let i = 0; i < this.rings.length; i++) {\r\n const ring = this.rings[i];\r\n\r\n result += ring.id + ';';\r\n result += ring.members.length + ';';\r\n result += ring.neighbours.length + ';';\r\n result += ring.isSpiro ? 'true;' : 'false;';\r\n result += ring.isFused ? 'true;' : 'false;';\r\n result += ring.isBridged ? 'true;' : 'false;';\r\n result += ring.rings.length + ';';\r\n result += '\\n';\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Rotates the drawing to make the widest dimension horizontal.\r\n */\r\n rotateDrawing() {\r\n // Rotate the vertices to make the molecule align horizontally\r\n // Find the longest distance\r\n let a = 0;\r\n let b = 0;\r\n let maxDist = 0;\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertexA = this.graph.vertices[i];\r\n\r\n if (!vertexA.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n for (let j = i + 1; j < this.graph.vertices.length; j++) {\r\n let vertexB = this.graph.vertices[j];\r\n\r\n if (!vertexB.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = vertexA.position.distanceSq(vertexB.position);\r\n\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n a = i;\r\n b = j;\r\n }\r\n }\r\n }\r\n\r\n let angle = -Vector2.subtract(this.graph.vertices[a].position, this.graph.vertices[b].position).angle();\r\n\r\n if (!isNaN(angle)) {\r\n // Round to 30 degrees\r\n let remainder = angle % 0.523599;\r\n\r\n // Round either up or down in 30 degree steps\r\n if (remainder < 0.2617995) {\r\n angle = angle - remainder;\r\n } else {\r\n angle += 0.523599 - remainder;\r\n }\r\n\r\n // Finally, rotate everything\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (i === b) {\r\n continue;\r\n }\r\n\r\n this.graph.vertices[i].position.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.rings[i].center.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.totalOverlapScore;\r\n }\r\n\r\n /**\r\n * Returns the ring count of the current molecule.\r\n *\r\n * @returns {Number} The ring count.\r\n */\r\n getRingCount() {\r\n return this.rings.length;\r\n }\r\n\r\n /**\r\n * Checks whether or not the current molecule a bridged ring.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not the current molecule a bridged ring.\r\n */\r\n hasBridgedRing() {\r\n return this.bridgedRing;\r\n }\r\n\r\n /**\r\n * Returns the number of heavy atoms (non-hydrogen) in the current molecule.\r\n *\r\n * @returns {Number} The heavy atom count.\r\n */\r\n getHeavyAtomCount() {\r\n let hac = 0;\r\n\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.element !== 'H') {\r\n hac++;\r\n }\r\n }\r\n\r\n return hac;\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n let molecularFormula = '';\r\n let counts = new Map();\r\n\r\n // Initialize element count\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n let atom = this.graph.vertices[i].value;\r\n\r\n if (counts.has(atom.element)) {\r\n counts.set(atom.element, counts.get(atom.element) + 1);\r\n } else {\r\n counts.set(atom.element, 1);\r\n }\r\n\r\n // Hydrogens attached to a chiral center were added as vertices,\r\n // those in non chiral brackets are added here\r\n if (atom.bracket && !atom.bracket.chirality) {\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + atom.bracket.hcount);\r\n } else {\r\n counts.set('H', atom.bracket.hcount);\r\n }\r\n }\r\n\r\n // Add the implicit hydrogens according to valency, exclude\r\n // bracket atoms as they were handled and always have the number\r\n // of hydrogens specified explicitly\r\n if (!atom.bracket) {\r\n let nHydrogens = Atom.maxBonds[atom.element] - atom.bondCount;\r\n\r\n if (atom.isPartOfAromaticRing) {\r\n nHydrogens--;\r\n }\r\n\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + nHydrogens);\r\n } else {\r\n counts.set('H', nHydrogens);\r\n }\r\n }\r\n }\r\n\r\n if (counts.has('C')) {\r\n let count = counts.get('C');\r\n molecularFormula += 'C' + (count > 1 ? count : '');\r\n counts.delete('C');\r\n }\r\n\r\n if (counts.has('H')) {\r\n let count = counts.get('H');\r\n molecularFormula += 'H' + (count > 1 ? count : '');\r\n counts.delete('H');\r\n }\r\n\r\n let elements = Object.keys(Atom.atomicNumbers).sort();\r\n\r\n elements.map(e => {\r\n if (counts.has(e)) {\r\n let count = counts.get(e);\r\n molecularFormula += e + (count > 1 ? count : '');\r\n }\r\n });\r\n\r\n return molecularFormula;\r\n }\r\n\r\n /**\r\n * Returns the type of the ringbond (e.g. '=' for a double bond). The ringbond represents the break in a ring introduced when creating the MST. If the two vertices supplied as arguments are not part of a common ringbond, the method returns null.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(String|null)} Returns the ringbond type or null, if the two supplied vertices are not connected by a ringbond.\r\n */\r\n getRingbondType(vertexA, vertexB) {\r\n // Checks whether the two vertices are the ones connecting the ring\r\n // and what the bond type should be.\r\n if (vertexA.value.getRingbondCount() < 1 || vertexB.value.getRingbondCount() < 1) {\r\n return null;\r\n }\r\n\r\n for (var i = 0; i < vertexA.value.ringbonds.length; i++) {\r\n for (var j = 0; j < vertexB.value.ringbonds.length; j++) {\r\n // if(i != j) continue;\r\n if (vertexA.value.ringbonds[i].id === vertexB.value.ringbonds[j].id) {\r\n // If the bonds are equal, it doesn't matter which bond is returned.\r\n // if they are not equal, return the one that is not the default (\"-\")\r\n if (vertexA.value.ringbonds[i].bondType === '-') {\r\n return vertexB.value.ringbonds[j].bond;\r\n } else {\r\n return vertexA.value.ringbonds[i].bond;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n initDraw(data, themeName, infoOnly) {\r\n this.data = data;\r\n this.infoOnly = infoOnly;\r\n\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n\r\n this.graph = new Graph(data, this.opts.isomeric, this.opts);\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n this.bridgedRing = false;\r\n\r\n // Reset those, in case the previous drawn SMILES had a dangling \\ or /\r\n this.doubleBondConfigCount = null;\r\n this.doubleBondConfig = null;\r\n\r\n this.initRings();\r\n this.initHydrogens();\r\n this.graph.findDecayPoints();\r\n }\r\n\r\n processGraph() {\r\n this.position();\r\n\r\n // Restore the ring information (removes bridged rings and replaces them with the original, multiple, rings)\r\n this.restoreRingInformation();\r\n\r\n // Atoms bonded to the same ring atom\r\n this.resolvePrimaryOverlaps();\r\n\r\n let overlapScore = this.getOverlapScore();\r\n\r\n this.totalOverlapScore = this.getOverlapScore().total;\r\n\r\n for (var o = 0; o < this.opts.overlapResolutionIterations; o++) {\r\n for (var i = 0; i < this.graph.edges.length; i++) {\r\n let edge = this.graph.edges[i];\r\n if (this.isEdgeRotatable(edge)) {\r\n let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\r\n let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\r\n\r\n // Only rotate the shorter subtree\r\n let a = edge.targetId;\r\n let b = edge.sourceId;\r\n\r\n if (subTreeDepthA > subTreeDepthB) {\r\n a = edge.sourceId;\r\n b = edge.targetId;\r\n }\r\n\r\n let subTreeOverlap = this.getSubtreeOverlapScore(b, a, overlapScore.vertexScores);\r\n if (subTreeOverlap.value > this.opts.overlapSensitivity) {\r\n let vertexA = this.graph.vertices[a];\r\n let vertexB = this.graph.vertices[b];\r\n let neighboursB = vertexB.getNeighbours(a);\r\n\r\n if (neighboursB.length === 1) {\r\n let neighbour = this.graph.vertices[neighboursB[0]];\r\n let angle = neighbour.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbour.id, vertexB.id, angle, vertexB.position);\r\n // If the new overlap is bigger, undo change\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbour.id, vertexB.id, -angle, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n } else if (neighboursB.length === 2) {\r\n // Switch places / sides\r\n // If vertex a is in a ring, do nothing\r\n if (vertexB.value.rings.length !== 0 && vertexA.value.rings.length !== 0) {\r\n continue;\r\n }\r\n\r\n let neighbourA = this.graph.vertices[neighboursB[0]];\r\n let neighbourB = this.graph.vertices[neighboursB[1]];\r\n\r\n if (neighbourA.value.rings.length === 1 && neighbourB.value.rings.length === 1) {\r\n // Both neighbours in same ring. TODO: does this create problems with wedges? (up = down and vice versa?)\r\n if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\r\n continue;\r\n }\r\n // TODO: Rotate circle\r\n } else if (neighbourA.value.rings.length !== 0 || neighbourB.value.rings.length !== 0) {\r\n continue;\r\n } else {\r\n let angleA = neighbourA.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n let angleB = neighbourB.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbourA.id, vertexB.id, angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, angleB, vertexB.position);\r\n\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbourA.id, vertexB.id, -angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, -angleB, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n }\r\n }\r\n\r\n overlapScore = this.getOverlapScore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.resolveSecondaryOverlaps(overlapScore.scores);\r\n\r\n if (this.opts.isomeric) {\r\n this.annotateStereochemistry();\r\n }\r\n\r\n // Initialize pseudo elements or shortcuts\r\n if (this.opts.compactDrawing && this.opts.atomVisualization === 'default') {\r\n this.initPseudoElements();\r\n }\r\n\r\n this.rotateDrawing();\r\n }\r\n\r\n /**\r\n * Initializes rings and ringbonds for the current molecule.\r\n */\r\n initRings() {\r\n let openBonds = new Map();\r\n\r\n // Close the open ring bonds (spanning tree -> graph)\r\n for (let i = this.graph.vertices.length - 1; i >= 0; i--) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.ringbonds.length === 0) {\r\n continue;\r\n }\r\n\r\n for (let j = 0; j < vertex.value.ringbonds.length; j++) {\r\n let ringbondId = vertex.value.ringbonds[j].id;\r\n let ringbondBond = vertex.value.ringbonds[j].bond;\r\n\r\n // If the other ringbond id has not been discovered,\r\n // add it to the open bonds map and continue.\r\n // if the other ringbond id has already been discovered,\r\n // create a bond between the two atoms.\r\n if (!openBonds.has(ringbondId)) {\r\n openBonds.set(ringbondId, [vertex.id, ringbondBond]);\r\n } else {\r\n let sourceVertexId = vertex.id;\r\n let targetVertexId = openBonds.get(ringbondId)[0];\r\n let targetRingbondBond = openBonds.get(ringbondId)[1];\r\n let edge = new Edge(sourceVertexId, targetVertexId, 1);\r\n edge.setBondType(targetRingbondBond || ringbondBond || '-');\r\n let edgeId = this.graph.addEdge(edge);\r\n let targetVertex = this.graph.vertices[targetVertexId];\r\n\r\n vertex.addRingbondChild(targetVertexId, j);\r\n vertex.value.addNeighbouringElement(targetVertex.value.element);\r\n targetVertex.addRingbondChild(sourceVertexId, j);\r\n targetVertex.value.addNeighbouringElement(vertex.value.element);\r\n vertex.edges.push(edgeId);\r\n targetVertex.edges.push(edgeId);\r\n\r\n openBonds.delete(ringbondId);\r\n }\r\n }\r\n }\r\n\r\n // Get the rings in the graph (the SSSR)\r\n let rings = SSSR.getRings(this.graph, this.opts.experimentalSSSR);\r\n\r\n if (rings === null) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < rings.length; i++) {\r\n let ringVertices = [...rings[i]];\r\n let ringId = this.addRing(new Ring(ringVertices));\r\n\r\n // Add the ring to the atoms\r\n for (let j = 0; j < ringVertices.length; j++) {\r\n this.graph.vertices[ringVertices[j]].value.rings.push(ringId);\r\n }\r\n }\r\n\r\n // Find connection between rings\r\n // Check for common vertices and create ring connections. This is a bit\r\n // ugly, but the ringcount is always fairly low (< 100)\r\n for (let i = 0; i < this.rings.length - 1; i++) {\r\n for (let j = i + 1; j < this.rings.length; j++) {\r\n let a = this.rings[i];\r\n let b = this.rings[j];\r\n let ringConnection = new RingConnection(a, b);\r\n\r\n // If there are no vertices in the ring connection, then there\r\n // is no ring connection\r\n if (ringConnection.vertices.size > 0) {\r\n this.addRingConnection(ringConnection);\r\n }\r\n }\r\n }\r\n\r\n // Add neighbours to the rings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n ring.neighbours = RingConnection.getNeighbours(this.ringConnections, ring.id);\r\n }\r\n\r\n // Anchor the ring to one of it's members, so that the ring center will always\r\n // be tied to a single vertex when doing repositionings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n this.graph.vertices[ring.members[0]].value.addAnchoredRing(ring.id);\r\n }\r\n\r\n // Backup the ring information to restore after placing the bridged ring.\r\n // This is needed in order to identify aromatic rings and stuff like this in\r\n // rings that are member of the superring.\r\n this.backupRingInformation();\r\n\r\n\r\n // Replace rings contained by a larger bridged ring with a bridged ring\r\n while (this.rings.length > 0) {\r\n let id = -1;\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isPartOfBridgedRing(ring.id) && !ring.isBridged) {\r\n id = ring.id;\r\n }\r\n }\r\n\r\n if (id === -1) {\r\n break;\r\n }\r\n\r\n let ring = this.getRing(id);\r\n\r\n let involvedRings = this.getBridgedRingRings(ring.id);\r\n\r\n this.bridgedRing = true;\r\n this.createBridgedRing(involvedRings, ring.members[0]);\r\n\r\n // Remove the rings\r\n for (let i = 0; i < involvedRings.length; i++) {\r\n this.removeRing(involvedRings[i]);\r\n }\r\n }\r\n }\r\n\r\n initHydrogens() {\r\n // Do not draw hydrogens except when they are connected to a stereocenter connected to two or more rings.\r\n if (!this.opts.explicitHydrogens) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.element !== 'H') {\r\n continue;\r\n }\r\n\r\n // Hydrogens should have only one neighbour, so just take the first\r\n // Also set hasHydrogen true on connected atom\r\n let neighbour = this.graph.vertices[vertex.neighbours[0]];\r\n neighbour.value.hasHydrogen = true;\r\n\r\n if (!neighbour.value.isStereoCenter || neighbour.value.rings.length < 2 && !neighbour.value.bridgedRing ||\r\n neighbour.value.bridgedRing && neighbour.value.originalRings.length < 2) {\r\n vertex.value.isDrawn = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns all rings connected by bridged bonds starting from the ring with the supplied ring id.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array containing all ring ids of rings part of a bridged ring system.\r\n */\r\n getBridgedRingRings(ringId) {\r\n let involvedRings = Array();\r\n let that = this;\r\n\r\n let recurse = function (r) {\r\n let ring = that.getRing(r);\r\n\r\n involvedRings.push(r);\r\n\r\n for (let i = 0; i < ring.neighbours.length; i++) {\r\n let n = ring.neighbours[i];\r\n\r\n if (involvedRings.indexOf(n) === -1 &&\r\n n !== r &&\r\n RingConnection.isBridge(that.ringConnections, that.graph.vertices, r, n)) {\r\n recurse(n);\r\n }\r\n }\r\n };\r\n\r\n recurse(ringId);\r\n\r\n return ArrayHelper.unique(involvedRings);\r\n }\r\n\r\n /**\r\n * Checks whether or not a ring is part of a bridged ring.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not the supplied ring (by id) is part of a bridged ring system.\r\n */\r\n isPartOfBridgedRing(ringId) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].containsRing(ringId) &&\r\n this.ringConnections[i].isBridge(this.graph.vertices)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Creates a bridged ring.\r\n *\r\n * @param {Number[]} ringIds An array of ids of rings involved in the bridged ring.\r\n * @param {Number} sourceVertexId The vertex id to start the bridged ring discovery from.\r\n * @returns {Ring} The bridged ring.\r\n */\r\n createBridgedRing(ringIds, sourceVertexId) {\r\n let ringMembers = new Set();\r\n let vertices = new Set();\r\n let neighbours = new Set();\r\n\r\n for (let i = 0; i < ringIds.length; i++) {\r\n let ring = this.getRing(ringIds[i]);\r\n ring.isPartOfBridged = true;\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n vertices.add(ring.members[j]);\r\n }\r\n\r\n for (let j = 0; j < ring.neighbours.length; j++) {\r\n let id = ring.neighbours[j];\r\n\r\n if (ringIds.indexOf(id) === -1) {\r\n neighbours.add(ring.neighbours[j]);\r\n }\r\n }\r\n }\r\n\r\n // A vertex is part of the bridged ring if it only belongs to\r\n // one of the rings (or to another ring\r\n // which is not part of the bridged ring).\r\n let leftovers = new Set();\r\n\r\n for (let id of vertices) {\r\n let vertex = this.graph.vertices[id];\r\n let intersection = ArrayHelper.intersection(ringIds, vertex.value.rings);\r\n\r\n if (vertex.value.rings.length === 1 || intersection.length === 1) {\r\n ringMembers.add(vertex.id);\r\n } else {\r\n leftovers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Vertices can also be part of multiple rings and lay on the bridged ring,\r\n // however, they have to have at least two neighbours that are not part of\r\n // two rings\r\n let insideRing = Array();\r\n for (let id of leftovers) {\r\n let vertex = this.graph.vertices[id];\r\n let onRing = false;\r\n\r\n for (let j = 0; j < vertex.edges.length; j++) {\r\n if (this.edgeRingCount(vertex.edges[j]) === 1) {\r\n onRing = true;\r\n }\r\n }\r\n\r\n if (onRing) {\r\n vertex.value.isBridgeNode = true;\r\n ringMembers.add(vertex.id);\r\n } else {\r\n vertex.value.isBridge = true;\r\n ringMembers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Create the ring\r\n let ring = new Ring([...ringMembers]);\r\n this.addRing(ring);\r\n\r\n ring.isBridged = true;\r\n ring.neighbours = [...neighbours];\r\n for (let i = 0; i < ringIds.length; i++) {\r\n ring.rings.push(this.getRing(ringIds[i]).clone());\r\n }\r\n\r\n for (let i = 0; i < ring.members.length; i++) {\r\n this.graph.vertices[ring.members[i]].value.bridgedRing = ring.id;\r\n }\r\n\r\n // Atoms inside the ring are no longer part of a ring but are now\r\n // associated with the bridged ring\r\n for (let i = 0; i < insideRing.length; i++) {\r\n let vertex = this.graph.vertices[insideRing[i]];\r\n vertex.value.rings = Array();\r\n }\r\n\r\n // Remove former rings from members of the bridged ring and add the bridged ring\r\n for (let id of ringMembers) {\r\n let vertex = this.graph.vertices[id];\r\n vertex.value.rings = ArrayHelper.removeAll(vertex.value.rings, ringIds);\r\n vertex.value.rings.push(ring.id);\r\n }\r\n\r\n // Remove all the ring connections no longer used\r\n for (let i = 0; i < ringIds.length; i++) {\r\n for (let j = i + 1; j < ringIds.length; j++) {\r\n this.removeRingConnectionsBetween(ringIds[i], ringIds[j]);\r\n }\r\n }\r\n\r\n // Update the ring connections and add this ring to the neighbours neighbours\r\n for (let id of neighbours) {\r\n let connections = this.getRingConnections(id, ringIds);\r\n\r\n for (let j = 0; j < connections.length; j++) {\r\n this.getRingConnection(connections[j]).updateOther(ring.id, id);\r\n }\r\n\r\n this.getRing(id).neighbours.push(ring.id);\r\n }\r\n\r\n return ring;\r\n }\r\n\r\n /**\r\n * Checks whether or not two vertices are in the same ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices are in the same ring.\r\n */\r\n areVerticesInSameRing(vertexA, vertexB) {\r\n // This is a little bit lighter (without the array and push) than\r\n // getCommonRings().length > 0\r\n for (let i = 0; i < vertexA.value.rings.length; i++) {\r\n for (let j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] === vertexB.value.rings[j]) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array of ring ids shared by both vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Number[]} An array of ids of rings shared by the two vertices.\r\n */\r\n getCommonRings(vertexA, vertexB) {\r\n let commonRings = Array();\r\n\r\n for (var i = 0; i < vertexA.value.rings.length; i++) {\r\n for (var j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] == vertexB.value.rings[j]) {\r\n commonRings.push(vertexA.value.rings[i]);\r\n }\r\n }\r\n }\r\n\r\n return commonRings;\r\n }\r\n\r\n /**\r\n * Returns the aromatic or largest ring shared by the two vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(Ring|null)} If an aromatic common ring exists, that ring, else the largest (non-aromatic) ring, else null.\r\n */\r\n getLargestOrAromaticCommonRing(vertexA, vertexB) {\r\n let commonRings = this.getCommonRings(vertexA, vertexB);\r\n let maxSize = 0;\r\n let largestCommonRing = null;\r\n\r\n for (let i = 0; i < commonRings.length; i++) {\r\n let ring = this.getRing(commonRings[i]);\r\n let size = ring.getSize();\r\n\r\n if (ring.isBenzeneLike(this.graph.vertices)) {\r\n return ring;\r\n } else if (size > maxSize) {\r\n maxSize = size;\r\n largestCommonRing = ring;\r\n }\r\n }\r\n\r\n return largestCommonRing;\r\n }\r\n\r\n /**\r\n * Returns an array of vertices positioned at a specified location.\r\n *\r\n * @param {Vector2} position The position to search for vertices.\r\n * @param {Number} radius The radius within to search.\r\n * @param {Number} excludeVertexId A vertex id to be excluded from the search results.\r\n * @returns {Number[]} An array containing vertex ids in a given location.\r\n */\r\n getVerticesAt(position, radius, excludeVertexId) {\r\n let locals = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.id === excludeVertexId || !vertex.positioned) {\r\n continue;\r\n }\r\n\r\n let distance = position.distanceSq(vertex.position);\r\n\r\n if (distance <= radius * radius) {\r\n locals.push(vertex.id);\r\n }\r\n }\r\n\r\n return locals;\r\n }\r\n\r\n /**\r\n * Returns the closest vertex (connected as well as unconnected).\r\n *\r\n * @param {Vertex} vertex The vertex of which to find the closest other vertex.\r\n * @returns {Vertex} The closest vertex.\r\n */\r\n getClosestVertex(vertex) {\r\n let minDist = 99999;\r\n let minVertex = null;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i];\r\n\r\n if (v.id === vertex.id) {\r\n continue;\r\n }\r\n\r\n let distSq = vertex.position.distanceSq(v.position);\r\n\r\n if (distSq < minDist) {\r\n minDist = distSq;\r\n minVertex = v;\r\n }\r\n }\r\n\r\n return minVertex;\r\n }\r\n\r\n /**\r\n * Add a ring to this representation of a molecule.\r\n *\r\n * @param {Ring} ring A new ring.\r\n * @returns {Number} The ring id of the new ring.\r\n */\r\n addRing(ring) {\r\n ring.id = this.ringIdCounter++;\r\n this.rings.push(ring);\r\n\r\n return ring.id;\r\n }\r\n\r\n /**\r\n * Removes a ring from the array of rings associated with the current molecule.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n removeRing(ringId) {\r\n this.rings = this.rings.filter(function (item) {\r\n return item.id !== ringId;\r\n });\r\n\r\n // Also remove ring connections involving this ring\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.firstRingId !== ringId && item.secondRingId !== ringId;\r\n });\r\n\r\n // Remove the ring as neighbour of other rings\r\n for (var i = 0; i < this.rings.length; i++) {\r\n let r = this.rings[i];\r\n r.neighbours = r.neighbours.filter(function (item) {\r\n return item !== ringId;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets a ring object from the array of rings associated with the current molecule by its id. The ring id is not equal to the index, since rings can be added and removed when processing bridged rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Ring} A ring associated with the current molecule.\r\n */\r\n getRing(ringId) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].id == ringId) {\r\n return this.rings[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Add a ring connection to this representation of a molecule.\r\n *\r\n * @param {RingConnection} ringConnection A new ringConnection.\r\n * @returns {Number} The ring connection id of the new ring connection.\r\n */\r\n addRingConnection(ringConnection) {\r\n ringConnection.id = this.ringConnectionIdCounter++;\r\n this.ringConnections.push(ringConnection);\r\n\r\n return ringConnection.id;\r\n }\r\n\r\n /**\r\n * Removes a ring connection from the array of rings connections associated with the current molecule.\r\n *\r\n * @param {Number} ringConnectionId A ring connection id.\r\n */\r\n removeRingConnection(ringConnectionId) {\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.id !== ringConnectionId;\r\n });\r\n }\r\n\r\n /**\r\n * Removes all ring connections between two vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n */\r\n removeRingConnectionsBetween(vertexIdA, vertexIdB) {\r\n let toRemove = Array();\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let ringConnection = this.ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === vertexIdA && ringConnection.secondRingId === vertexIdB ||\r\n ringConnection.firstRingId === vertexIdB && ringConnection.secondRingId === vertexIdA) {\r\n toRemove.push(ringConnection.id);\r\n }\r\n }\r\n\r\n for (let i = 0; i < toRemove.length; i++) {\r\n this.removeRingConnection(toRemove[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Get a ring connection with a given id.\r\n *\r\n * @param {Number} id\r\n * @returns {RingConnection} The ring connection with the specified id.\r\n */\r\n getRingConnection(id) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].id == id) {\r\n return this.ringConnections[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the ring connections between a ring and a set of rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @param {Number[]} ringIds An array of ring ids.\r\n * @returns {Number[]} An array of ring connection ids.\r\n */\r\n getRingConnections(ringId, ringIds) {\r\n let ringConnections = Array();\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let rc = this.ringConnections[i];\r\n\r\n for (let j = 0; j < ringIds.length; j++) {\r\n let id = ringIds[j];\r\n\r\n if (rc.firstRingId === ringId && rc.secondRingId === id ||\r\n rc.firstRingId === id && rc.secondRingId === ringId) {\r\n ringConnections.push(rc.id);\r\n }\r\n }\r\n }\r\n\r\n return ringConnections;\r\n }\r\n\r\n /**\r\n * Returns the overlap score of the current molecule based on its positioned vertices. The higher the score, the more overlaps occur in the structure drawing.\r\n *\r\n * @returns {Object} Returns the total overlap score and the overlap score of each vertex sorted by score (higher to lower). Example: { total: 99, scores: [ { id: 0, score: 22 }, ... ] }\r\n */\r\n getOverlapScore() {\r\n let total = 0.0;\r\n let overlapScores = new Float32Array(this.graph.vertices.length);\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n overlapScores[i] = 0;\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let j = this.graph.vertices.length;\r\n while (--j > i) {\r\n let a = this.graph.vertices[i];\r\n let b = this.graph.vertices[j];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = Vector2.subtract(a.position, b.position).lengthSq();\r\n\r\n if (dist < this.opts.bondLengthSq) {\r\n let weighted = (this.opts.bondLength - Math.sqrt(dist)) / this.opts.bondLength;\r\n total += weighted;\r\n overlapScores[i] += weighted;\r\n overlapScores[j] += weighted;\r\n }\r\n }\r\n }\r\n\r\n let sortable = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n sortable.push({\r\n id: i,\r\n score: overlapScores[i]\r\n });\r\n }\r\n\r\n sortable.sort(function (a, b) {\r\n return b.score - a.score;\r\n });\r\n\r\n return {\r\n total: total,\r\n scores: sortable,\r\n vertexScores: overlapScores\r\n };\r\n }\r\n\r\n /**\r\n * When drawing a double bond, choose the side to place the double bond. E.g. a double bond should always been drawn inside a ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @param {Vector2[]} sides An array containing the two normals of the line spanned by the two provided vertices.\r\n * @returns {Object} Returns an object containing the following information: {\r\n totalSideCount: Counts the sides of each vertex in the molecule, is an array [ a, b ],\r\n totalPosition: Same as position, but based on entire molecule,\r\n sideCount: Counts the sides of each neighbour, is an array [ a, b ],\r\n position: which side to position the second bond, is 0 or 1, represents the index in the normal array. This is based on only the neighbours\r\n anCount: the number of neighbours of vertexA,\r\n bnCount: the number of neighbours of vertexB\r\n }\r\n */\r\n chooseSide(vertexA, vertexB, sides) {\r\n // Check which side has more vertices\r\n // Get all the vertices connected to the both ends\r\n let an = vertexA.getNeighbours(vertexB.id);\r\n let bn = vertexB.getNeighbours(vertexA.id);\r\n let anCount = an.length;\r\n let bnCount = bn.length;\r\n\r\n // All vertices connected to the edge vertexA to vertexB\r\n let tn = ArrayHelper.merge(an, bn);\r\n\r\n // Only considering the connected vertices\r\n let sideCount = [0, 0];\r\n\r\n for (let i = 0; i < tn.length; i++) {\r\n let v = this.graph.vertices[tn[i]].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n sideCount[0]++;\r\n } else {\r\n sideCount[1]++;\r\n }\r\n }\r\n\r\n // Considering all vertices in the graph, this is to resolve ties\r\n // from the above side counts\r\n let totalSideCount = [0, 0];\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n totalSideCount[0]++;\r\n } else {\r\n totalSideCount[1]++;\r\n }\r\n }\r\n\r\n return {\r\n totalSideCount: totalSideCount,\r\n totalPosition: totalSideCount[0] > totalSideCount[1] ? 0 : 1,\r\n sideCount: sideCount,\r\n position: sideCount[0] > sideCount[1] ? 0 : 1,\r\n anCount: anCount,\r\n bnCount: bnCount\r\n };\r\n }\r\n\r\n /**\r\n * Sets the center for a ring.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n setRingCenter(ring) {\r\n let ringSize = ring.getSize();\r\n let total = new Vector2(0, 0);\r\n\r\n for (let i = 0; i < ringSize; i++) {\r\n total.add(this.graph.vertices[ring.members[i]].position);\r\n }\r\n\r\n ring.center = total.divide(ringSize);\r\n }\r\n\r\n /**\r\n * Gets the center of a ring contained within a bridged ring and containing a given vertex.\r\n *\r\n * @param {Ring} ring A bridged ring.\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {Vector2} The center of the subring that containing the vertex.\r\n */\r\n getSubringCenter(ring, vertex) {\r\n let rings = vertex.value.originalRings;\r\n let center = ring.center;\r\n let smallest = Number.MAX_VALUE;\r\n\r\n // Always get the smallest ring.\r\n for (let i = 0; i < rings.length; i++) {\r\n for (let j = 0; j < ring.rings.length; j++) {\r\n if (rings[i] === ring.rings[j].id) {\r\n if (ring.rings[j].getSize() < smallest) {\r\n center = ring.rings[j].center;\r\n smallest = ring.rings[j].getSize();\r\n }\r\n }\r\n }\r\n }\r\n\r\n return center;\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let that = this;\r\n let drawn = Array(this.graph.edges.length);\r\n drawn.fill(false);\r\n\r\n this.graph.traverseBF(0, function (vertex) {\r\n let edges = that.graph.getEdges(vertex.id);\r\n for (let i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n that.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isRingAromatic(ring)) {\r\n this.canvasWrapper.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bonds to the canvas.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let that = this;\r\n let edge = this.graph.edges[edgeId];\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n let elementA = vertexA.value.element;\r\n let elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && this.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position;\r\n let b = vertexB.position;\r\n let normals = this.getEdgeNormals(edge);\r\n\r\n // Create a point on each side of the line\r\n let sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || this.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && this.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = this.areVerticesInSameRing(vertexA, vertexB);\r\n let s = this.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = this.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n }\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n this.canvasWrapper.drawLine(line, true);\r\n } else {\r\n this.canvasWrapper.drawLine(line);\r\n }\r\n\r\n // The normal edge\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.center || vertexA.isTerminal() && vertexB.isTerminal()) {\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1) {\r\n // Both lines are the same length here\r\n // Add the spacing to the edges (which are of unit length)\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.sideCount[0] > s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.sideCount[0] < s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] > s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] <= s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n this.canvasWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.wedge === 'down') {\r\n this.canvasWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else {\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n this.canvasWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(this.graph.vertices);\r\n let isTerminal = this.opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (this.opts.atomVisualization === 'allballs') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || this.graph.vertices.length === 1) {\r\n if (this.opts.atomVisualization === 'default') {\r\n this.canvasWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (this.opts.atomVisualization === 'balls') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = this.graph.vertices[vertex.neighbours[0]].position;\r\n let b = this.graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n this.canvasWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n // this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (this.opts.debug) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let center = this.rings[i].center;\r\n this.canvasWrapper.drawDebugPoint(center.x, center.y, 'r: ' + this.rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Position the vertices according to their bonds and properties.\r\n */\r\n position() {\r\n let startVertex = null;\r\n\r\n // Always start drawing at a bridged ring if there is one\r\n // If not, start with a ring\r\n // else, start with 0\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.bridgedRing !== null) {\r\n startVertex = this.graph.vertices[i];\r\n break;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n startVertex = this.graph.vertices[this.rings[i].members[0]];\r\n }\r\n }\r\n\r\n if (this.rings.length > 0 && startVertex === null) {\r\n startVertex = this.graph.vertices[this.rings[0].members[0]];\r\n }\r\n\r\n if (startVertex === null) {\r\n startVertex = this.graph.vertices[0];\r\n }\r\n\r\n this.createNextBond(startVertex, null, 0.0);\r\n }\r\n\r\n /**\r\n * Stores the current information associated with rings.\r\n */\r\n backupRingInformation() {\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings.push(this.rings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n this.originalRingConnections.push(this.ringConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.backupRings();\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recently backed up information associated with rings.\r\n */\r\n restoreRingInformation() {\r\n // Get the subring centers from the bridged rings\r\n let bridgedRings = this.getBridgedRings();\r\n\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n for (let i = 0; i < bridgedRings.length; i++) {\r\n let bridgedRing = bridgedRings[i];\r\n\r\n for (var j = 0; j < bridgedRing.rings.length; j++) {\r\n let ring = bridgedRing.rings[j];\r\n this.originalRings[ring.id].center = ring.center;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings.push(this.originalRings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.originalRingConnections.length; i++) {\r\n this.ringConnections.push(this.originalRingConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.restoreRings();\r\n }\r\n }\r\n\r\n // TODO: This needs some cleaning up\r\n\r\n /**\r\n * Creates a new ring, that is, positiones all the vertices inside a ring.\r\n *\r\n * @param {Ring} ring The ring to position.\r\n * @param {(Vector2|null)} [center=null] The center of the ring to be created.\r\n * @param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.\r\n * @param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.\r\n * @param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.\r\n */\r\n createRing(ring, center = null, startVertex = null, previousVertex = null) {\r\n if (ring.positioned) {\r\n return;\r\n }\r\n\r\n center = center ? center : new Vector2(0, 0);\r\n\r\n let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);\r\n let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let angle = MathHelper.centralAngle(ring.getSize());\r\n\r\n ring.centralAngle = angle;\r\n\r\n let a = startingAngle;\r\n let that = this;\r\n let startVertexId = (startVertex) ? startVertex.id : null;\r\n\r\n if (ring.members.indexOf(startVertexId) === -1) {\r\n if (startVertex) {\r\n startVertex.positioned = false;\r\n }\r\n\r\n startVertexId = ring.members[0];\r\n }\r\n\r\n // If the ring is bridged, then draw the vertices inside the ring\r\n // using a force based approach\r\n if (ring.isBridged) {\r\n this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength,\r\n this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration,\r\n this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);\r\n ring.positioned = true;\r\n\r\n // Update the center of the bridged ring\r\n this.setRingCenter(ring);\r\n center = ring.center;\r\n\r\n // Setting the centers for the subrings\r\n for (let i = 0; i < ring.rings.length; i++) {\r\n this.setRingCenter(ring.rings[i]);\r\n }\r\n } else {\r\n ring.eachMember(this.graph.vertices, function (v) {\r\n let vertex = that.graph.vertices[v];\r\n\r\n if (!vertex.positioned) {\r\n vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);\r\n }\r\n\r\n a += angle;\r\n\r\n if (!ring.isBridged || ring.rings.length < 3) {\r\n vertex.angle = a;\r\n vertex.positioned = true;\r\n }\r\n }, startVertexId, (previousVertex) ? previousVertex.id : null);\r\n }\r\n\r\n ring.positioned = true;\r\n ring.center = center;\r\n\r\n // Draw neighbours in decreasing order of connectivity\r\n for (let i = 0; i < orderedNeighbours.length; i++) {\r\n let neighbour = this.getRing(orderedNeighbours[i].neighbour);\r\n\r\n if (neighbour.positioned) {\r\n continue;\r\n }\r\n\r\n let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);\r\n\r\n if (vertices.length === 2) {\r\n // This ring is a fused ring\r\n ring.isFused = true;\r\n neighbour.isFused = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n let vertexB = this.graph.vertices[vertices[1]];\r\n\r\n // Get middle between vertex A and B\r\n let midpoint = Vector2.midpoint(vertexA.position, vertexB.position);\r\n\r\n // Get the normals to the line between A and B\r\n let normals = Vector2.normals(vertexA.position, vertexB.position);\r\n\r\n // Normalize the normals\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n // Set length from middle of side to center (the apothem)\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n let apothem = MathHelper.apothem(r, neighbour.getSize());\r\n\r\n normals[0].multiplyScalar(apothem).add(midpoint);\r\n normals[1].multiplyScalar(apothem).add(midpoint);\r\n\r\n // Pick the normal which results in a larger distance to the previous center\r\n // Also check whether it's inside another ring\r\n let nextCenter = normals[0];\r\n if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {\r\n nextCenter = normals[1];\r\n }\r\n\r\n // Get the vertex (A or B) which is in clock-wise direction of the other\r\n let posA = Vector2.subtract(vertexA.position, nextCenter);\r\n let posB = Vector2.subtract(vertexB.position, nextCenter);\r\n\r\n if (posA.clockwise(posB) === -1) {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA, vertexB);\r\n }\r\n } else {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexB, vertexA);\r\n }\r\n }\r\n } else if (vertices.length === 1) {\r\n // This ring is a spiro\r\n ring.isSpiro = true;\r\n neighbour.isSpiro = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n\r\n // Get the vector pointing from the shared vertex to the new centpositioner\r\n let nextCenter = Vector2.subtract(center, vertexA.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n // Get the distance from the vertex to the center\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertexA.position);\r\n\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA);\r\n }\r\n }\r\n }\r\n\r\n // Next, draw atoms that are not part of a ring that are directly attached to this ring\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let ringMember = this.graph.vertices[ring.members[i]];\r\n let ringMemberNeighbours = ringMember.neighbours;\r\n\r\n // If there are multiple, the ovlerap will be resolved in the appropriate step\r\n for (let j = 0; j < ringMemberNeighbours.length; j++) {\r\n let v = this.graph.vertices[ringMemberNeighbours[j]];\r\n\r\n if (v.positioned) {\r\n continue;\r\n }\r\n\r\n v.value.isConnectedToRing = true;\r\n this.createNextBond(v, ringMember, 0.0);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Rotate an entire subtree by an angle around a center.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree that is to rotate.\r\n * @param {Number} angle An angle in randians.\r\n * @param {Vector2} center The rotational center.\r\n */\r\n rotateSubtree(vertexId, parentVertexId, angle, center) {\r\n let that = this;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n vertex.position.rotateAround(angle, center);\r\n\r\n for (var i = 0; i < vertex.value.anchoredRings.length; i++) {\r\n let ring = that.rings[vertex.value.anchoredRings[i]];\r\n\r\n if (ring) {\r\n ring.center.rotateAround(angle, center);\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Gets the overlap score of a subtree.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree.\r\n * @param {Number[]} vertexOverlapScores An array containing the vertex overlap scores indexed by vertex id.\r\n * @returns {Object} An object containing the total overlap score and the center of mass of the subtree weighted by overlap score { value: 0.2, center: new Vector2() }.\r\n */\r\n getSubtreeOverlapScore(vertexId, parentVertexId, vertexOverlapScores) {\r\n let that = this;\r\n let score = 0;\r\n let center = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n if (!vertex.value.isDrawn) {\r\n return;\r\n }\r\n\r\n let s = vertexOverlapScores[vertex.id];\r\n if (s > that.opts.overlapSensitivity) {\r\n score += s;\r\n count++;\r\n }\r\n\r\n let position = that.graph.vertices[vertex.id].position.clone();\r\n position.multiplyScalar(s);\r\n center.add(position);\r\n });\r\n\r\n center.divide(score);\r\n\r\n return {\r\n value: score / count,\r\n center: center\r\n };\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass.\r\n *\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMass() {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass in the neighbourhood of a given position.\r\n *\r\n * @param {Vector2} vec The point at which to look for neighbours.\r\n * @param {Number} [r=currentBondLength*2.0] The radius of vertices to include.\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMassInNeigbourhood(vec, r = this.opts.bondLength * 2.0) {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n let rSq = r * r;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned && vec.distanceSq(vertex.position) < rSq) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Resolve primary (exact) overlaps, such as two vertices that are connected to the same ring vertex.\r\n */\r\n resolvePrimaryOverlaps() {\r\n let overlaps = Array();\r\n let done = Array(this.graph.vertices.length);\r\n\r\n // Looking for overlaps created by two bonds coming out of a ring atom, which both point straight\r\n // away from the ring and are thus perfectly overlapping.\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n let vertex = this.graph.vertices[ring.members[j]];\r\n\r\n if (done[vertex.id]) {\r\n continue;\r\n }\r\n\r\n done[vertex.id] = true;\r\n\r\n let nonRingNeighbours = this.getNonRingNeighbours(vertex.id);\r\n\r\n if (nonRingNeighbours.length > 1) {\r\n // Look for rings where there are atoms with two bonds outside the ring (overlaps)\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n } else if (nonRingNeighbours.length === 1 && vertex.value.rings.length === 2) {\r\n // Look for bonds coming out of joined rings to adjust the angle, an example is: C1=CC(=CC=C1)[C@]12SCCN1CC1=CC=CC=C21\r\n // where the angle has to be adjusted to account for fused ring\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (let i = 0; i < overlaps.length; i++) {\r\n let overlap = overlaps[i];\r\n\r\n if (overlap.vertices.length === 2) {\r\n let a = overlap.vertices[0];\r\n let b = overlap.vertices[1];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let angle = (2 * Math.PI - this.getRing(overlap.rings[0]).getAngle()) / 6.0;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -angle, overlap.common.position);\r\n\r\n // Decide which way to rotate the vertices depending on the effect it has on the overlap score\r\n let overlapScore = this.getOverlapScore();\r\n let subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n let subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n let total = subTreeOverlapA.value + subTreeOverlapB.value;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n\r\n overlapScore = this.getOverlapScore();\r\n subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n\r\n if (subTreeOverlapA.value + subTreeOverlapB.value > total) {\r\n this.rotateSubtree(a.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n }\r\n } else if (overlap.vertices.length === 1) {\r\n if (overlap.rings.length === 2) {\r\n // TODO: Implement for more overlap resolution\r\n // console.log(overlap);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resolve secondary overlaps. Those overlaps are due to the structure turning back on itself.\r\n *\r\n * @param {Object[]} scores An array of objects sorted descending by score.\r\n * @param {Number} scores[].id A vertex id.\r\n * @param {Number} scores[].score The overlap score associated with the vertex id.\r\n */\r\n resolveSecondaryOverlaps(scores) {\r\n for (let i = 0; i < scores.length; i++) {\r\n if (scores[i].score > this.opts.overlapSensitivity) {\r\n let vertex = this.graph.vertices[scores[i].id];\r\n\r\n if (vertex.isTerminal()) {\r\n let closest = this.getClosestVertex(vertex);\r\n\r\n if (closest) {\r\n // If one of the vertices is the first one, the previous vertex is not the central vertex but the dummy\r\n // so take the next rather than the previous, which is vertex 1\r\n let closestPosition = null;\r\n\r\n if (closest.isTerminal()) {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.previousPosition\r\n } else {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.position\r\n }\r\n\r\n let vertexPreviousPosition = vertex.id === 0 ? this.graph.vertices[1].position : vertex.previousPosition;\r\n\r\n vertex.position.rotateAwayFrom(closestPosition, vertexPreviousPosition, MathHelper.toRad(20));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the last non-null or 0 angle vertex.\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex} The last vertex with an angle that was not 0 or null.\r\n */\r\n getLastVertexWithAngle(vertexId) {\r\n let angle = 0;\r\n let vertex = null;\r\n\r\n while (!angle && vertexId) {\r\n vertex = this.graph.vertices[vertexId];\r\n angle = vertex.angle;\r\n vertexId = vertex.parentVertexId;\r\n }\r\n\r\n return vertex;\r\n }\r\n\r\n /**\r\n * Positiones the next vertex thus creating a bond.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @param {Vertex} [previousVertex=null] The previous vertex which has been positioned.\r\n * @param {Number} [angle=0.0] The (global) angle of the vertex.\r\n * @param {Boolean} [originShortest=false] Whether the origin is the shortest subtree in the branch.\r\n * @param {Boolean} [skipPositioning=false] Whether or not to skip positioning and just check the neighbours.\r\n */\r\n createNextBond(vertex, previousVertex = null, angle = 0.0, originShortest = false, skipPositioning = false) {\r\n if (vertex.positioned && !skipPositioning) {\r\n return;\r\n }\r\n\r\n // If the double bond config was set on this vertex, do not check later\r\n let doubleBondConfigSet = false;\r\n\r\n // Keeping track of configurations around double bonds\r\n if (previousVertex) {\r\n let edge = this.graph.getEdge(vertex.id, previousVertex.id);\r\n\r\n if ((edge.bondType === '/' || edge.bondType === '\\\\') && ++this.doubleBondConfigCount % 2 === 1) {\r\n if (this.doubleBondConfig === null) {\r\n this.doubleBondConfig = edge.bondType;\r\n doubleBondConfigSet = true;\r\n\r\n // Switch if the bond is a branch bond and previous vertex is the first\r\n // TODO: Why is it different with the first vertex?\r\n if (previousVertex.parentVertexId === null && vertex.value.branchBond) {\r\n if (this.doubleBondConfig === '/') {\r\n this.doubleBondConfig = '\\\\';\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n this.doubleBondConfig = '/';\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If the current node is the member of one ring, then point straight away\r\n // from the center of the ring. However, if the current node is a member of\r\n // two rings, point away from the middle of the centers of the two rings\r\n if (!skipPositioning) {\r\n if (!previousVertex) {\r\n // Add a (dummy) previous position if there is no previous vertex defined\r\n // Since the first vertex is at (0, 0), create a vector at (bondLength, 0)\r\n // and rotate it by 90°\r\n\r\n let dummy = new Vector2(this.opts.bondLength, 0);\r\n dummy.rotate(MathHelper.toRad(-60));\r\n\r\n vertex.previousPosition = dummy;\r\n vertex.setPosition(this.opts.bondLength, 0);\r\n vertex.angle = MathHelper.toRad(-60);\r\n\r\n // Do not position the vertex if it belongs to a bridged ring that is positioned using a layout algorithm.\r\n if (vertex.value.bridgedRing === null) {\r\n vertex.positioned = true;\r\n }\r\n } else if (previousVertex.value.rings.length > 0) {\r\n let neighbours = previousVertex.neighbours;\r\n let joinedVertex = null;\r\n let pos = new Vector2(0.0, 0.0);\r\n\r\n if (previousVertex.value.bridgedRing === null && previousVertex.value.rings.length > 1) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n if (ArrayHelper.containsAll(neighbour.value.rings, previousVertex.value.rings)) {\r\n joinedVertex = neighbour;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (joinedVertex === null) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let v = this.graph.vertices[neighbours[i]];\r\n\r\n if (v.positioned && this.areVerticesInSameRing(v, previousVertex)) {\r\n pos.add(Vector2.subtract(v.position, previousVertex.position));\r\n }\r\n }\r\n\r\n pos.invert().normalize().multiplyScalar(this.opts.bondLength).add(previousVertex.position);\r\n } else {\r\n pos = joinedVertex.position.clone().rotateAround(Math.PI, previousVertex.position);\r\n }\r\n\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.setPositionFromVector(pos);\r\n vertex.positioned = true;\r\n } else {\r\n // If the previous vertex was not part of a ring, draw a bond based\r\n // on the global angle of the previous bond\r\n let v = new Vector2(this.opts.bondLength, 0);\r\n\r\n v.rotate(angle);\r\n v.add(previousVertex.position);\r\n\r\n vertex.setPositionFromVector(v);\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.positioned = true;\r\n }\r\n }\r\n\r\n // Go to next vertex\r\n // If two rings are connected by a bond ...\r\n if (vertex.value.bridgedRing !== null) {\r\n let nextRing = this.getRing(vertex.value.bridgedRing);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.members.length);\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else if (vertex.value.rings.length > 0) {\r\n let nextRing = this.getRing(vertex.value.rings[0]);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else {\r\n // Draw the non-ring vertices connected to this one\r\n let isStereoCenter = vertex.value.isStereoCenter;\r\n let tmpNeighbours = vertex.getNeighbours();\r\n let neighbours = Array();\r\n\r\n // Remove neighbours that are not drawn\r\n for (let i = 0; i < tmpNeighbours.length; i++) {\r\n if (this.graph.vertices[tmpNeighbours[i]].value.isDrawn) {\r\n neighbours.push(tmpNeighbours[i]);\r\n }\r\n }\r\n\r\n // Remove the previous vertex (which has already been drawn)\r\n if (previousVertex) {\r\n neighbours = ArrayHelper.remove(neighbours, previousVertex.id);\r\n }\r\n\r\n let previousAngle = vertex.getAngle();\r\n\r\n if (neighbours.length === 1) {\r\n let nextVertex = this.graph.vertices[neighbours[0]];\r\n\r\n // Make a single chain always cis except when there's a tribble (yes, this is a Star Trek reference) bond\r\n // or if there are successive double bonds. Added a ring check because if there is an aromatic ring the ring bond inside the ring counts as a double bond and leads to =-= being straight.\r\n if ((vertex.value.bondType === '#' || (previousVertex && previousVertex.value.bondType === '#')) ||\r\n vertex.value.bondType === '=' && previousVertex && previousVertex.value.rings.length === 0 &&\r\n previousVertex.value.bondType === '=' && vertex.value.branchBond !== '-') {\r\n vertex.value.drawExplicit = false;\r\n\r\n if (previousVertex) {\r\n let straightEdge1 = this.graph.getEdge(vertex.id, previousVertex.id);\r\n straightEdge1.center = true;\r\n }\r\n\r\n let straightEdge2 = this.graph.getEdge(vertex.id, nextVertex.id);\r\n straightEdge2.center = true;\r\n\r\n if (vertex.value.bondType === '#' || previousVertex && previousVertex.value.bondType === '#') {\r\n nextVertex.angle = 0.0;\r\n }\r\n\r\n nextVertex.drawExplicit = true;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else if (previousVertex && previousVertex.value.rings.length > 0) {\r\n // If coming out of a ring, always draw away from the center of mass\r\n let proposedAngleA = MathHelper.toRad(60);\r\n let proposedAngleB = -proposedAngleA;\r\n\r\n let proposedVectorA = new Vector2(this.opts.bondLength, 0);\r\n let proposedVectorB = new Vector2(this.opts.bondLength, 0);\r\n\r\n proposedVectorA.rotate(proposedAngleA).add(vertex.position);\r\n proposedVectorB.rotate(proposedAngleB).add(vertex.position);\r\n\r\n // let centerOfMass = this.getCurrentCenterOfMassInNeigbourhood(vertex.position, 100);\r\n let centerOfMass = this.getCurrentCenterOfMass();\r\n let distanceA = proposedVectorA.distanceSq(centerOfMass);\r\n let distanceB = proposedVectorB.distanceSq(centerOfMass);\r\n\r\n nextVertex.angle = distanceA < distanceB ? proposedAngleB : proposedAngleA;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else {\r\n let a = vertex.angle;\r\n // Take the min and max if the previous angle was in a 4-neighbourhood (90° angles)\r\n // TODO: If a is null or zero, it should be checked whether or not this one should go cis or trans, that is,\r\n // it should go into the oposite direction of the last non-null or 0 previous vertex / angle.\r\n if (previousVertex && previousVertex.neighbours.length > 3) {\r\n if (a > 0) {\r\n a = Math.min(1.0472, a);\r\n } else if (a < 0) {\r\n a = Math.max(-1.0472, a);\r\n } else {\r\n a = 1.0472;\r\n }\r\n } else if (!a) {\r\n let v = this.getLastVertexWithAngle(vertex.id);\r\n a = v.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n }\r\n\r\n // Handle configuration around double bonds\r\n if (previousVertex && !doubleBondConfigSet) {\r\n let bondType = this.graph.getEdge(vertex.id, nextVertex.id).bondType;\r\n\r\n if (bondType === '/') {\r\n if (this.doubleBondConfig === '/') {\r\n // Nothing to do since it will be trans per default\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n a = -a;\r\n }\r\n this.doubleBondConfig = null;\r\n } else if (bondType === '\\\\') {\r\n if (this.doubleBondConfig === '/') {\r\n a = -a;\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n // Nothing to do since it will be trans per default\r\n }\r\n this.doubleBondConfig = null;\r\n }\r\n }\r\n\r\n if (originShortest) {\r\n nextVertex.angle = a;\r\n } else {\r\n nextVertex.angle = -a;\r\n }\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n }\r\n } else if (neighbours.length === 2) {\r\n // If the previous vertex comes out of a ring, it doesn't have an angle set\r\n let a = vertex.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n\r\n // Check for the longer subtree - always go with cis for the longer subtree\r\n let subTreeDepthA = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let subTreeDepthB = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n\r\n let l = this.graph.vertices[neighbours[0]];\r\n let r = this.graph.vertices[neighbours[1]];\r\n\r\n l.value.subtreeDepth = subTreeDepthA;\r\n r.value.subtreeDepth = subTreeDepthB;\r\n\r\n // Also get the subtree for the previous direction (this is important when\r\n // the previous vertex is the shortest path)\r\n let subTreeDepthC = this.graph.getTreeDepth(previousVertex ? previousVertex.id : null, vertex.id);\r\n if (previousVertex) {\r\n previousVertex.value.subtreeDepth = subTreeDepthC;\r\n }\r\n\r\n let cis = 0;\r\n let trans = 1;\r\n\r\n // Carbons go always cis\r\n if (r.value.element === 'C' && l.value.element !== 'C' && subTreeDepthB > 1 && subTreeDepthA < 5) {\r\n cis = 1;\r\n trans = 0;\r\n } else if (r.value.element !== 'C' && l.value.element === 'C' && subTreeDepthA > 1 && subTreeDepthB < 5) {\r\n cis = 0;\r\n trans = 1;\r\n } else if (subTreeDepthB > subTreeDepthA) {\r\n cis = 1;\r\n trans = 0;\r\n }\r\n\r\n let cisVertex = this.graph.vertices[neighbours[cis]];\r\n let transVertex = this.graph.vertices[neighbours[trans]];\r\n\r\n // If the origin tree is the shortest, make them the main chain\r\n let originShortest = false;\r\n if (subTreeDepthC < subTreeDepthA && subTreeDepthC < subTreeDepthB) {\r\n originShortest = true;\r\n }\r\n\r\n transVertex.angle = a;\r\n cisVertex.angle = -a;\r\n\r\n if (this.doubleBondConfig === '\\\\') {\r\n if (transVertex.value.branchBond === '\\\\') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n } else if (this.doubleBondConfig === '/') {\r\n if (transVertex.value.branchBond === '/') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n }\r\n\r\n this.createNextBond(transVertex, vertex, previousAngle + transVertex.angle, originShortest);\r\n this.createNextBond(cisVertex, vertex, previousAngle + cisVertex.angle, originShortest);\r\n } else if (neighbours.length === 3) {\r\n // The vertex with the longest sub-tree should always go straight\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n\r\n let s = this.graph.vertices[neighbours[0]];\r\n let l = this.graph.vertices[neighbours[1]];\r\n let r = this.graph.vertices[neighbours[2]];\r\n\r\n s.value.subtreeDepth = d1;\r\n l.value.subtreeDepth = d2;\r\n r.value.subtreeDepth = d3;\r\n\r\n if (d2 > d1 && d2 > d3) {\r\n s = this.graph.vertices[neighbours[1]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[2]];\r\n } else if (d3 > d1 && d3 > d2) {\r\n s = this.graph.vertices[neighbours[2]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[1]];\r\n }\r\n\r\n // Create a cross if more than one subtree is of length > 1\r\n // or the vertex is connected to a ring\r\n if (previousVertex &&\r\n previousVertex.value.rings.length < 1 &&\r\n s.value.rings.length < 1 &&\r\n l.value.rings.length < 1 &&\r\n r.value.rings.length < 1 &&\r\n this.graph.getTreeDepth(l.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(r.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(s.id, vertex.id) > 1) {\r\n\r\n s.angle = -vertex.angle;\r\n if (vertex.angle >= 0) {\r\n l.angle = MathHelper.toRad(30);\r\n r.angle = MathHelper.toRad(90);\r\n } else {\r\n l.angle = -MathHelper.toRad(30);\r\n r.angle = -MathHelper.toRad(90);\r\n }\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n } else {\r\n s.angle = 0.0;\r\n l.angle = MathHelper.toRad(90);\r\n r.angle = -MathHelper.toRad(90);\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n }\r\n } else if (neighbours.length === 4) {\r\n // The vertex with the longest sub-tree should always go to the reflected opposide direction\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n let d4 = this.graph.getTreeDepth(neighbours[3], vertex.id);\r\n\r\n let w = this.graph.vertices[neighbours[0]];\r\n let x = this.graph.vertices[neighbours[1]];\r\n let y = this.graph.vertices[neighbours[2]];\r\n let z = this.graph.vertices[neighbours[3]];\r\n\r\n w.value.subtreeDepth = d1;\r\n x.value.subtreeDepth = d2;\r\n y.value.subtreeDepth = d3;\r\n z.value.subtreeDepth = d4;\r\n\r\n if (d2 > d1 && d2 > d3 && d2 > d4) {\r\n w = this.graph.vertices[neighbours[1]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[2]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d3 > d1 && d3 > d2 && d3 > d4) {\r\n w = this.graph.vertices[neighbours[2]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d4 > d1 && d4 > d2 && d4 > d3) {\r\n w = this.graph.vertices[neighbours[3]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[2]];\r\n }\r\n\r\n w.angle = -MathHelper.toRad(36);\r\n x.angle = MathHelper.toRad(36);\r\n y.angle = -MathHelper.toRad(108);\r\n z.angle = MathHelper.toRad(108);\r\n\r\n this.createNextBond(w, vertex, previousAngle + w.angle);\r\n this.createNextBond(x, vertex, previousAngle + x.angle);\r\n this.createNextBond(y, vertex, previousAngle + y.angle);\r\n this.createNextBond(z, vertex, previousAngle + z.angle);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Gets the vetex sharing the edge that is the common bond of two rings.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {(Number|null)} The id of a vertex sharing the edge that is the common bond of two rings with the vertex provided or null, if none.\r\n */\r\n getCommonRingbondNeighbour(vertex) {\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n\r\n if (ArrayHelper.containsAll(neighbour.value.rings, vertex.value.rings)) {\r\n return neighbour;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Check if a vector is inside any ring.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Boolean} A boolean indicating whether or not the point (vector) is inside any of the rings associated with the current molecule.\r\n */\r\n isPointInRing(vec) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (!ring.positioned) {\r\n continue;\r\n }\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let radiusSq = radius * radius;\r\n\r\n if (vec.distanceSq(ring.center) < radiusSq) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is part of a ring.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is part of a ring.\r\n */\r\n isEdgeInRing(edge) {\r\n let source = this.graph.vertices[edge.sourceId];\r\n let target = this.graph.vertices[edge.targetId];\r\n\r\n return this.areVerticesInSameRing(source, target);\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is rotatable.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is rotatable.\r\n */\r\n isEdgeRotatable(edge) {\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n\r\n // Only single bonds are rotatable\r\n if (edge.bondType !== '-') {\r\n return false;\r\n }\r\n\r\n // Do not rotate edges that have a further single bond to each side - do that!\r\n // If the bond is terminal, it doesn't make sense to rotate it\r\n // if (vertexA.getNeighbourCount() + vertexB.getNeighbourCount() < 5) {\r\n // return false;\r\n // }\r\n\r\n if (vertexA.isTerminal() || vertexB.isTerminal()) {\r\n return false;\r\n }\r\n\r\n // Ringbonds are not rotatable\r\n return !(vertexA.value.rings.length > 0 && vertexB.value.rings.length > 0 && this.areVerticesInSameRing(vertexA, vertexB));\r\n }\r\n\r\n /**\r\n * Check whether or not a ring is an implicitly defined aromatic ring (lower case smiles).\r\n *\r\n * @param {Ring} ring A ring.\r\n * @returns {Boolean} A boolean indicating whether or not a ring is implicitly defined as aromatic.\r\n */\r\n isRingAromatic(ring) {\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let vertex = this.graph.vertices[ring.members[i]];\r\n\r\n if (!vertex.value.isPartOfAromaticRing) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the normals of an edge.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Vector2[]} An array containing two vectors, representing the normals.\r\n */\r\n getEdgeNormals(edge) {\r\n let v1 = this.graph.vertices[edge.sourceId].position;\r\n let v2 = this.graph.vertices[edge.targetId].position;\r\n\r\n // Get the normalized normals for the edge\r\n return Vector2.units(v1, v2);\r\n }\r\n\r\n /**\r\n * Returns an array of vertices that are neighbouring a vertix but are not members of a ring (including bridges).\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex[]} An array of vertices.\r\n */\r\n getNonRingNeighbours(vertexId) {\r\n let nrneighbours = Array();\r\n let vertex = this.graph.vertices[vertexId];\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n let nIntersections = ArrayHelper.intersection(vertex.value.rings, neighbour.value.rings).length;\r\n\r\n if (nIntersections === 0 && neighbour.value.isBridge == false) {\r\n nrneighbours.push(neighbour);\r\n }\r\n }\r\n\r\n return nrneighbours;\r\n }\r\n\r\n /**\r\n * Annotaed stereochemistry information for visualization.\r\n */\r\n annotateStereochemistry() {\r\n let maxDepth = 10;\r\n\r\n // For each stereo-center\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (!vertex.value.isStereoCenter) {\r\n continue;\r\n }\r\n\r\n let neighbours = vertex.getNeighbours();\r\n let nNeighbours = neighbours.length;\r\n let priorities = Array(nNeighbours);\r\n\r\n for (let j = 0; j < nNeighbours; j++) {\r\n let visited = new Uint8Array(this.graph.vertices.length);\r\n let priority = Array(Array());\r\n visited[vertex.id] = 1;\r\n\r\n this.visitStereochemistry(neighbours[j], vertex.id, visited, priority, maxDepth, 0);\r\n\r\n // Sort each level according to atomic number\r\n for (let k = 0; k < priority.length; k++) {\r\n priority[k].sort(function (a, b) {\r\n return b - a\r\n });\r\n }\r\n\r\n priorities[j] = [j, priority];\r\n }\r\n\r\n let maxLevels = 0;\r\n let maxEntries = 0;\r\n for (let j = 0; j < priorities.length; j++) {\r\n if (priorities[j][1].length > maxLevels) {\r\n maxLevels = priorities[j][1].length;\r\n }\r\n\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n if (priorities[j][1][k].length > maxEntries) {\r\n maxEntries = priorities[j][1][k].length;\r\n }\r\n }\r\n }\r\n\r\n for (let j = 0; j < priorities.length; j++) {\r\n let diff = maxLevels - priorities[j][1].length;\r\n for (let k = 0; k < diff; k++) {\r\n priorities[j][1].push([]);\r\n }\r\n\r\n // Break ties by the position in the SMILES string as per specification\r\n priorities[j][1].push([neighbours[j]]);\r\n\r\n // Make all same length. Fill with zeroes.\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n let diff = maxEntries - priorities[j][1][k].length;\r\n\r\n for (let l = 0; l < diff; l++) {\r\n priorities[j][1][k].push(0);\r\n }\r\n }\r\n }\r\n\r\n priorities.sort(function (a, b) {\r\n for (let j = 0; j < a[1].length; j++) {\r\n for (let k = 0; k < a[1][j].length; k++) {\r\n if (a[1][j][k] > b[1][j][k]) {\r\n return -1;\r\n } else if (a[1][j][k] < b[1][j][k]) {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n\r\n let order = new Uint8Array(nNeighbours);\r\n for (let j = 0; j < nNeighbours; j++) {\r\n order[j] = priorities[j][0];\r\n vertex.value.priority = j;\r\n }\r\n\r\n // Check the angles between elements 0 and 1, and 0 and 2 to determine whether they are\r\n // drawn cw or ccw\r\n // TODO: OC(Cl)=[C@]=C(C)F currently fails here, however this is, IMHO, not a valid SMILES.\r\n let posA = this.graph.vertices[neighbours[order[0]]].position;\r\n let posB = this.graph.vertices[neighbours[order[1]]].position;\r\n\r\n let cwA = posA.relativeClockwise(posB, vertex.position);\r\n\r\n // If the second priority is clockwise from the first, the ligands are drawn clockwise, since\r\n // The hydrogen can be drawn on either side\r\n let isCw = cwA === -1;\r\n\r\n let rotation = vertex.value.bracket.chirality === '@' ? -1 : 1;\r\n let rs = MathHelper.parityOfPermutation(order) * rotation === 1 ? 'R' : 'S';\r\n\r\n // Flip the hydrogen direction when the drawing doesn't match the chirality.\r\n let wedgeA = 'down';\r\n let wedgeB = 'up';\r\n if (isCw && rs !== 'R' || !isCw && rs !== 'S') {\r\n vertex.value.hydrogenDirection = 'up';\r\n wedgeA = 'up';\r\n wedgeB = 'down';\r\n }\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, neighbours[order[order.length - 1]]).wedge = wedgeA;\r\n }\r\n\r\n // Get the shortest subtree to flip up / down. Ignore lowest priority\r\n // The rules are following:\r\n // 1. Do not draw wedge between two stereocenters\r\n // 2. Heteroatoms\r\n // 3. Draw outside ring\r\n // 4. Shortest subtree\r\n\r\n let wedgeOrder = new Array(neighbours.length - 1);\r\n let showHydrogen = vertex.value.rings.length > 1 && vertex.value.hasHydrogen;\r\n let offset = vertex.value.hasHydrogen ? 1 : 0;\r\n\r\n for (let j = 0; j < order.length - offset; j++) {\r\n wedgeOrder[j] = new Uint32Array(2);\r\n let neighbour = this.graph.vertices[neighbours[order[j]]];\r\n wedgeOrder[j][0] += neighbour.value.isStereoCenter ? 0 : 100000;\r\n // wedgeOrder[j][0] += neighbour.value.rings.length > 0 ? 0 : 10000;\r\n // Only add if in same ring, unlike above\r\n wedgeOrder[j][0] += this.areVerticesInSameRing(neighbour, vertex) ? 0 : 10000;\r\n wedgeOrder[j][0] += neighbour.value.isHeteroAtom() ? 1000 : 0;\r\n wedgeOrder[j][0] -= neighbour.value.subtreeDepth === 0 ? 1000 : 0;\r\n wedgeOrder[j][0] += 1000 - neighbour.value.subtreeDepth;\r\n wedgeOrder[j][1] = neighbours[order[j]];\r\n }\r\n\r\n\r\n wedgeOrder.sort(function (a, b) {\r\n if (a[0] > b[0]) {\r\n return -1;\r\n } else if (a[0] < b[0]) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n\r\n // If all neighbours are in a ring, do not draw wedge, the hydrogen will be drawn.\r\n if (!showHydrogen) {\r\n let wedgeId = wedgeOrder[0][1];\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedgeB;\r\n } else {\r\n let wedge = wedgeB;\r\n\r\n for (let j = order.length - 1; j >= 0; j--) {\r\n if (wedge === wedgeA) {\r\n wedge = wedgeB;\r\n } else {\r\n wedge = wedgeA;\r\n }\r\n if (neighbours[order[j]] === wedgeId) {\r\n break;\r\n }\r\n }\r\n\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedge;\r\n }\r\n }\r\n\r\n vertex.value.chirality = rs;\r\n }\r\n }\r\n\r\n /**\r\n *\r\n *\r\n * @param {Number} vertexId The id of a vertex.\r\n * @param {(Number|null)} previousVertexId The id of the parent vertex of the vertex.\r\n * @param {Uint8Array} visited An array containing the visited flag for all vertices in the graph.\r\n * @param {Array} priority An array of arrays storing the atomic numbers for each level.\r\n * @param {Number} maxDepth The maximum depth.\r\n * @param {Number} depth The current depth.\r\n * @param {Number} parentAtomicNumber\r\n */\r\n visitStereochemistry(vertexId, previousVertexId, visited, priority, maxDepth, depth, parentAtomicNumber = 0) {\r\n visited[vertexId] = 1;\r\n let vertex = this.graph.vertices[vertexId];\r\n let atomicNumber = vertex.value.getAtomicNumber();\r\n\r\n if (priority.length <= depth) {\r\n priority.push(Array());\r\n }\r\n\r\n for (let i = 0; i < this.graph.getEdge(vertexId, previousVertexId).weight; i++) {\r\n priority[depth].push(parentAtomicNumber * 1000 + atomicNumber);\r\n }\r\n\r\n let neighbours = this.graph.vertices[vertexId].neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (visited[neighbours[i]] !== 1 && depth < maxDepth - 1) {\r\n this.visitStereochemistry(neighbours[i], vertexId, visited.slice(), priority, maxDepth, depth + 1, atomicNumber);\r\n }\r\n }\r\n\r\n // Valences are filled with hydrogens and passed to the next level.\r\n if (depth < maxDepth - 1) {\r\n let bonds = 0;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n bonds += this.graph.getEdge(vertexId, neighbours[i]).weight;\r\n }\r\n\r\n for (let i = 0; i < vertex.value.getMaxBonds() - bonds; i++) {\r\n if (priority.length <= depth + 1) {\r\n priority.push(Array());\r\n }\r\n\r\n priority[depth + 1].push(atomicNumber * 1000 + 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Creates pseudo-elements (such as Et, Me, Ac, Bz, ...) at the position of the carbon sets\r\n * the involved atoms not to be displayed.\r\n */\r\n initPseudoElements() {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n // Ignore atoms that have less than 3 neighbours, except if\r\n // the vertex is connected to a ring and has two neighbours\r\n if (vertex.getNeighbourCount() < 3 || vertex.value.rings.length > 0) {\r\n continue;\r\n }\r\n\r\n // TODO: This exceptions should be handled more elegantly (via config file?)\r\n\r\n // Ignore phosphates (especially for triphosphates)\r\n if (vertex.value.element === 'P') {\r\n continue;\r\n }\r\n\r\n // Ignore also guanidine\r\n if (vertex.value.element === 'C' && neighbours.length === 3 &&\r\n neighbours[0].value.element === 'N' && neighbours[1].value.element === 'N' && neighbours[2].value.element === 'N') {\r\n continue;\r\n }\r\n\r\n // Continue if there are less than two heteroatoms\r\n // or if a neighbour has more than 1 neighbour\r\n let heteroAtomCount = 0;\r\n let ctn = 0;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n let neighbouringElement = neighbour.value.element;\r\n let neighbourCount = neighbour.getNeighbourCount();\r\n\r\n if (neighbouringElement !== 'C' && neighbouringElement !== 'H' &&\r\n neighbourCount === 1) {\r\n heteroAtomCount++;\r\n }\r\n\r\n if (neighbourCount > 1) {\r\n ctn++;\r\n }\r\n }\r\n\r\n if (ctn > 1 || heteroAtomCount < 2) {\r\n continue;\r\n }\r\n\r\n // Get the previous atom (the one which is not terminal)\r\n let previous = null;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n previous = neighbour;\r\n }\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n continue;\r\n }\r\n\r\n neighbour.value.isDrawn = false;\r\n\r\n let hydrogens = Atom.maxBonds[neighbour.value.element] - neighbour.value.bondCount;\r\n let charge = '';\r\n\r\n if (neighbour.value.bracket) {\r\n hydrogens = neighbour.value.bracket.hcount;\r\n charge = neighbour.value.bracket.charge || 0;\r\n }\r\n\r\n vertex.value.attachPseudoElement(neighbour.value.element, previous ? previous.value.element : null, hydrogens, charge);\r\n }\r\n }\r\n\r\n // The second pass\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const atom = vertex.value;\r\n const element = atom.element;\r\n\r\n if (element === 'C' || element === 'H' || !atom.isDrawn) {\r\n continue;\r\n }\r\n\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j].value;\r\n\r\n if (!neighbour.hasAttachedPseudoElements || neighbour.getAttachedPseudoElementsCount() !== 2) {\r\n continue;\r\n }\r\n\r\n const pseudoElements = neighbour.getAttachedPseudoElements();\r\n\r\n if (pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\r\n neighbour.isDrawn = false;\r\n vertex.value.attachPseudoElement('Ac', '', 0);\r\n }\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.graph.getDecays();\r\n }\r\n\r\n buildBlockSmiles() {\r\n return this.graph.buildSmiles();\r\n }\r\n\r\n /**\r\n * Find edge and mark it as decay point and redraw graph\r\n * @param e event\r\n */\r\n handleMouseClick(e) {\r\n if (this.opts.drawDecayPoints === DecayState.VALUES.NO) {\r\n return;\r\n }\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (!this.graph) {\r\n return;\r\n }\r\n this.findAndReDrawEdge(e.clientX - this.opts.offsetX, e.clientY - this.opts.offsetY + (document.documentElement.scrollTop || document.body.scrollTop));\r\n }\r\n\r\n /**\r\n * Find edge which was clicked, mark edge as decay point and redraw graph\r\n * @param mouseX mouse positionX - offsetX\r\n * @param mouseY mouse positionY - offsetY\r\n */\r\n findAndReDrawEdge(mouseX, mouseY) {\r\n for (let i = 0; i < this.graph.edges.length; ++i) {\r\n let vertexA = this.graph.vertices[this.graph.edges[i].sourceId];\r\n let vertexB = this.graph.vertices[this.graph.edges[i].targetId];\r\n if (!vertexA || !vertexB) {\r\n continue;\r\n }\r\n let scale = this.computeScale();\r\n let line = new Line(vertexA.position, vertexB.position, null, null, false, false, true);\r\n let l = this.computeEdgeLeftPoint(line, scale);\r\n let r = this.computeEdgeRightPoint(line, scale);\r\n if (mouseX < l.x - this.opts.mouseTolerance || mouseX > r.x + this.opts.mouseTolerance) {\r\n continue;\r\n }\r\n if ((mouseY > l.y - this.opts.mouseTolerance && mouseY < r.y + this.opts.mouseTolerance)\r\n || (mouseY > r.y - this.opts.mouseTolerance && mouseY < l.y + this.opts.mouseTolerance)) {\r\n this.reDrawGraphWithEdgeAsDecay(i);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Make edge decay point and redraw graph\r\n * @param {Number} edgeId\r\n */\r\n reDrawGraphWithEdgeAsDecay(edgeId) {\r\n this.graph.revertEdgeDecayPoint(edgeId);\r\n this.canvasWrapper.updateSize(this.opts.width, this.opts.height);\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n }\r\n\r\n /**\r\n * Compute scale of canvas\r\n * @return {number} scale\r\n */\r\n computeScale() {\r\n let scaleX = this.canvasWrapper.canvas.offsetWidth / this.canvasWrapper.drawingWidth;\r\n let scaleY = this.canvasWrapper.canvas.offsetHeight / this.canvasWrapper.drawingHeight;\r\n return (scaleX < scaleY) ? scaleX : scaleY;\r\n }\r\n\r\n /**\r\n * Compute left point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeLeftPoint(line, scale) {\r\n return this.computeEdgePoint(line.getLeftVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute right point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeRightPoint(line, scale) {\r\n return this.computeEdgePoint(line.getRightVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute point coordinates for compare\r\n * add offset to coordinates and multiply coordinates with scale\r\n * @param {Vector2} point\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgePoint(point, scale) {\r\n point.x += this.canvasWrapper.offsetX;\r\n point.y += this.canvasWrapper.offsetY;\r\n point.x *= scale;\r\n point.y *= scale;\r\n return point;\r\n }\r\n}\r\n\r\nmodule.exports = Drawer;\r\n","//@ts-check\r\n\r\n/** \r\n * A class representing an edge. \r\n * \r\n * @property {Number} id The id of this edge.\r\n * @property {Number} sourceId The id of the source vertex.\r\n * @property {Number} targetId The id of the target vertex.\r\n * @property {Number} weight The weight of this edge. That is, the degree of the bond (single bond = 1, double bond = 2, etc).\r\n * @property {String} [bondType='-'] The bond type of this edge.\r\n * @property {Boolean} [isPartOfAromaticRing=false] Whether or not this edge is part of an aromatic ring.\r\n * @property {Boolean} [center=false] Wheter or not the bond is centered. For example, this affects straight double bonds.\r\n * @property {String} [wedge=''] Wedge direction. Either '', 'up' or 'down'\r\n */\r\nclass Edge {\r\n /**\r\n * The constructor for the class Edge.\r\n *\r\n * @param {Number} sourceId A vertex id.\r\n * @param {Number} targetId A vertex id.\r\n * @param {Number} [weight=1] The weight of the edge.\r\n */\r\n constructor(sourceId, targetId, weight = 1) {\r\n this.id = null;\r\n this.sourceId = sourceId;\r\n this.targetId = targetId;\r\n this.weight = weight;\r\n this.bondType = '-';\r\n this.isPartOfAromaticRing = false;\r\n this.center = false;\r\n this.wedge = '';\r\n this.isDecay = false;\r\n this.isDecayAll = false;\r\n }\r\n\r\n /**\r\n * Set the bond type of this edge. This also sets the edge weight.\r\n * @param {String} bondType \r\n */\r\n setBondType(bondType) {\r\n this.bondType = bondType;\r\n this.weight = Edge.bonds[bondType];\r\n }\r\n\r\n /**\r\n * Set decay\r\n * @param {Boolean} decay point\r\n */\r\n setDecay(decay) {\r\n this.isDecay = decay;\r\n }\r\n\r\n /**\r\n * Set decay All\r\n * @param {Boolean} decay point\r\n */\r\n setDecayAll(decay) {\r\n this.isDecayAll = decay;\r\n }\r\n\r\n /**\r\n * An object mapping the bond type to the number of bonds.\r\n *\r\n * @returns {Object} The object containing the map.\r\n */\r\n static get bonds() {\r\n return {\r\n '-': 1,\r\n '/': 1,\r\n '\\\\': 1,\r\n '=': 2,\r\n '#': 3,\r\n '$': 4\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Edge;\r\n","//@ts-check\r\nconst DecayPoint = require('./DecayPoint');\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Ring = require('./Ring');\r\nconst Atom = require('./Atom');\r\nconst VertexState = require('./VertexState');\r\nconst SmallGraph = require('./SmallGraph');\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst DecayState = require('./DecayState');\r\nconst MutableBoolean = require('./MutableBoolean');\r\nconst MutableCounter = require('./MutableCounter');\r\nconst Direction = require('./Direction');\r\n\r\n/**\r\n * A class representing the molecular graph.\r\n *\r\n * @property {Vertex[]} vertices The vertices of the graph.\r\n * @property {Edge[]} edges The edges of this graph.\r\n * @property {Number[]} decays The id of edges marked as decay point of this graph.\r\n * @property {Object} vertexIdsToEdgeId A map mapping vertex ids to the edge between the two vertices. The key is defined as vertexAId + '_' + vertexBId.\r\n * @property {Boolean} isometric A boolean indicating whether or not the SMILES associated with this graph is isometric.\r\n */\r\nclass Graph {\r\n /**\r\n * The constructor of the class Graph.\r\n *\r\n * @param {Object} parseTree A SMILES parse tree.\r\n * @param {Boolean} [isomeric=false] A boolean specifying whether or not the SMILES is isomeric.\r\n * @param options\r\n */\r\n constructor(parseTree, isomeric = false, options = {}) {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.decays = Array();\r\n this.decaysAll = Array();\r\n this.vertexIdsToEdgeId = {};\r\n this.isomeric = isomeric;\r\n this._startingVertexes = [];\r\n this._isCyclic = false;\r\n this._polyketide = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.options = options;\r\n this._componentsIsPolyketide = [];\r\n\r\n // Used for the bridge detection algorithm\r\n this._time = 0;\r\n this._init(parseTree);\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION. Initializing the graph from the parse tree.\r\n *\r\n * @param {Object} node The current node in the parse tree.\r\n * @param order\r\n * @param {Number} parentVertexId=null The id of the previous vertex.\r\n * @param {Boolean} isBranch=false Whether or not the bond leading to this vertex is a branch bond. Branches are represented by parentheses in smiles (e.g. CC(O)C).\r\n */\r\n _init(node, order = 0, parentVertexId = null, isBranch = false) {\r\n // Create a new vertex object\r\n let atom = new Atom(node.atom.element ? node.atom.element : node.atom, node.bond);\r\n\r\n atom.branchBond = node.branchBond;\r\n atom.ringbonds = node.ringbonds;\r\n atom.bracket = node.atom.element ? node.atom : null;\r\n\r\n let vertex = new Vertex(atom);\r\n let parentVertex = this.vertices[parentVertexId];\r\n\r\n this.addVertex(vertex);\r\n\r\n // Add the id of this node to the parent as child\r\n if (parentVertexId !== null) {\r\n vertex.setParentVertexId(parentVertexId);\r\n vertex.value.addNeighbouringElement(parentVertex.value.element);\r\n parentVertex.addChild(vertex.id);\r\n parentVertex.value.addNeighbouringElement(atom.element);\r\n\r\n // In addition create a spanningTreeChildren property, which later will\r\n // not contain the children added through ringbonds\r\n parentVertex.spanningTreeChildren.push(vertex.id);\r\n\r\n // Add edge between this node and its parent\r\n let edge = new Edge(parentVertexId, vertex.id, 1);\r\n let vertexId;\r\n\r\n if (isBranch) {\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n } else {\r\n edge.setBondType(parentVertex.value.bondType || '-');\r\n vertexId = parentVertex.id;\r\n }\r\n\r\n this.addEdge(edge);\r\n }\r\n\r\n let offset = node.ringbondCount + 1;\r\n\r\n if (atom.bracket) {\r\n offset += atom.bracket.hcount;\r\n }\r\n\r\n let stereoHydrogens = 0;\r\n if (atom.bracket && atom.bracket.chirality) {\r\n atom.isStereoCenter = true;\r\n stereoHydrogens = atom.bracket.hcount;\r\n for (var i = 0; i < stereoHydrogens; i++) {\r\n this._init({\r\n atom: 'H',\r\n isBracket: 'false',\r\n branches: Array(),\r\n branchCount: 0,\r\n ringbonds: Array(),\r\n ringbondCount: false,\r\n next: null,\r\n hasNext: false,\r\n bond: '-'\r\n }, i, vertex.id, true);\r\n }\r\n }\r\n\r\n for (var i = 0; i < node.branchCount; i++) {\r\n this._init(node.branches[i], i + offset, vertex.id, true);\r\n }\r\n\r\n if (node.hasNext) {\r\n this._init(node.next, node.branchCount + offset, vertex.id);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of molecule\r\n * Types of decay points, declared in DecayPoint\r\n */\r\n findDecayPoints() {\r\n if (!Object.keys(this.options).length) {\r\n return;\r\n }\r\n\r\n switch (this.options.drawDecayPoints) {\r\n default:\r\n case DecayState.VALUES.NO:\r\n return;\r\n case DecayState.VALUES.STANDARD:\r\n this.standardDecays();\r\n break;\r\n case DecayState.VALUES.SOURCE:\r\n this.sourceDecays();\r\n break;\r\n case DecayState.VALUES.STANDARD_AND_SOURCE:\r\n this.standardDecays();\r\n this.sourceDecays();\r\n break;\r\n }\r\n }\r\n\r\n reduceDecays() {\r\n this._decaysCopy = [];\r\n this.dfsSmilesInitialization();\r\n for (let i = 0; i < this.decays.length; i++) {\r\n this.smallBlockDfsStart(this.edges[this.decays[i]]);\r\n }\r\n this.decays = [];\r\n this.decays = this._decaysCopy;\r\n this.setStandardDecays();\r\n }\r\n\r\n dfsSmallInitialization(vertices) {\r\n for (let i = 0; i < vertices.length; ++i) {\r\n this.vertices[vertices[i]].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n smallBlockDfsStart(edge) {\r\n let stackVisitedVertexes = [];\r\n let depth = this.smallDfs(this.vertices[edge.sourceId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n stackVisitedVertexes = [];\r\n depth = this.smallDfs(this.vertices[edge.targetId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n this._decaysCopy.push(edge.id);\r\n }\r\n }\r\n }\r\n\r\n smallDfs(vertex, depth, stackVisitedVertexes) {\r\n stackVisitedVertexes.push(vertex.id);\r\n if (depth > 3) {\r\n return depth;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return depth;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n ++depth;\r\n\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n depth = this.smallDfs(this.vertices[nextVertex], depth, stackVisitedVertexes);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n return depth;\r\n }\r\n\r\n setStandardDecays() {\r\n this.edges.forEach(e => {\r\n e.setDecay(false);\r\n });\r\n this.decays.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n });\r\n }\r\n\r\n standardDecays() {\r\n for (let i = 0; i < this.edges.length; i++) {\r\n if (this.edges[i].bondType === '=') {\r\n let dec = this.isDecayPoint(this.edges[i].sourceId, this.edges[i].targetId, i);\r\n if (dec !== false) {\r\n this.edges[dec].setDecay(true);\r\n this.decays.push(dec);\r\n this.edges[dec].setDecayAll(true);\r\n this.decaysAll.push(dec);\r\n }\r\n }\r\n }\r\n this.reduceDecays();\r\n }\r\n\r\n sourceDecays() {\r\n this.options.decaySource.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n this.edges[e].setDecayAll(true);\r\n this.decays.push(e);\r\n this.decaysAll.push(e);\r\n });\r\n }\r\n\r\n /**\r\n * check if its decay point of specific decay types\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @param decayTypes DecayPoint\r\n * @returns {int|boolean} return edge id when found, otherwise return false\r\n */\r\n isDecayPoint(sourceId, targetId, edgeBondId, decayTypes = DecayPoint.VALUES.ALL) {\r\n switch (decayTypes) {\r\n case DecayPoint.VALUES.ALL:\r\n let found = this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n if (found === false) {\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n } else {\r\n return found;\r\n }\r\n case DecayPoint.VALUES.COO:\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n case DecayPoint.VALUES.CONH:\r\n return this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-O- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'O', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'O', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-NH- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'N', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'N', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay point edge id of right neighbour\r\n * @param vertexId\r\n * @param element\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayId(vertexId, element, edgeBondId) {\r\n for (let i = 0; i < this.vertices[vertexId].edges.length; i++) {\r\n let edgeId = this.checkNeighbourEdgeId(this.vertices[vertexId].edges[i], vertexId, element);\r\n if (edgeId !== false && edgeId !== edgeBondId) {\r\n return edgeId;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find edge id of decay point\r\n * @param edgeId\r\n * @param vertexId\r\n * @param element\r\n * @returns {int|boolean}\r\n */\r\n checkNeighbourEdgeId(edgeId, vertexId, element) {\r\n if ((this.edges[edgeId].sourceId === vertexId && this.vertices[this.edges[edgeId].targetId].value.element === element) ||\r\n (this.edges[edgeId].targetId === vertexId && this.vertices[this.edges[edgeId].sourceId].value.element === element)) {\r\n return edgeId;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clears all the elements in this graph (edges and vertices).\r\n */\r\n clear() {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.vertexIdsToEdgeId = {};\r\n }\r\n\r\n /**\r\n * Add a vertex to the graph.\r\n *\r\n * @param {Vertex} vertex A new vertex.\r\n * @returns {Number} The vertex id of the new vertex.\r\n */\r\n addVertex(vertex) {\r\n vertex.id = this.vertices.length;\r\n this.vertices.push(vertex);\r\n\r\n return vertex.id;\r\n }\r\n\r\n /**\r\n * Add an edge to the graph.\r\n *\r\n * @param {Edge} edge A new edge.\r\n * @returns {Number} The edge id of the new edge.\r\n */\r\n addEdge(edge) {\r\n let source = this.vertices[edge.sourceId];\r\n let target = this.vertices[edge.targetId];\r\n\r\n edge.id = this.edges.length;\r\n this.edges.push(edge);\r\n\r\n this.vertexIdsToEdgeId[edge.sourceId + '_' + edge.targetId] = edge.id;\r\n this.vertexIdsToEdgeId[edge.targetId + '_' + edge.sourceId] = edge.id;\r\n edge.isPartOfAromaticRing = source.value.isPartOfAromaticRing && target.value.isPartOfAromaticRing;\r\n\r\n source.value.bondCount += edge.weight;\r\n target.value.bondCount += edge.weight;\r\n\r\n source.edges.push(edge.id);\r\n target.edges.push(edge.id);\r\n\r\n return edge.id;\r\n }\r\n\r\n /**\r\n * Returns the edge between two given vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {(Edge|null)} The edge or, if no edge can be found, null.\r\n */\r\n getEdge(vertexIdA, vertexIdB) {\r\n let edgeId = this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB];\r\n\r\n return edgeId === undefined ? null : this.edges[edgeId];\r\n }\r\n\r\n /**\r\n * Returns the ids of edges connected to a vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Number[]} An array containing the ids of edges connected to the vertex.\r\n */\r\n getEdges(vertexId) {\r\n let edgeIds = Array();\r\n let vertex = this.vertices[vertexId];\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n edgeIds.push(this.vertexIdsToEdgeId[vertexId + '_' + vertex.neighbours[i]]);\r\n }\r\n\r\n return edgeIds;\r\n }\r\n\r\n\r\n /**\r\n * Check whether or not two vertices are connected by an edge.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not two vertices are connected by an edge.\r\n */\r\n hasEdge(vertexIdA, vertexIdB) {\r\n return this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB] !== undefined\r\n }\r\n\r\n /**\r\n * Returns an array containing the vertex ids of this graph.\r\n *\r\n * @returns {Number[]} An array containing all vertex ids of this graph.\r\n */\r\n getVertexList() {\r\n let arr = [this.vertices.length];\r\n\r\n for (var i = 0; i < this.vertices.length; i++) {\r\n arr[i] = this.vertices[i].id;\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array containing source, target arrays of this graphs edges.\r\n *\r\n * @returns {Array[]} An array containing source, target arrays of this graphs edges. Example: [ [ 2, 5 ], [ 6, 9 ] ].\r\n */\r\n getEdgeList() {\r\n let arr = Array(this.edges.length);\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n arr[i] = [this.edges[i].sourceId, this.edges[i].targetId];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph.\r\n */\r\n getAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph with all bridges removed (thus the components). Thus the remaining vertices are all part of ring systems.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph with all bridges removed.\r\n */\r\n getComponentsAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n let bridges = this.getBridges();\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n for (var i = 0; i < bridges.length; i++) {\r\n adjacencyMatrix[bridges[i][0]][bridges[i][1]] = 0;\r\n adjacencyMatrix[bridges[i][1]][bridges[i][0]] = 0;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency matrix of the subgraph.\r\n */\r\n getSubgraphAdjacencyMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyMatrix[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of the graph.\r\n *\r\n * @returns {Array[]} The distance matrix of the graph.\r\n */\r\n getDistanceMatrix() {\r\n let length = this.vertices.length;\r\n let adja = this.getAdjacencyMatrix();\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The distance matrix of the subgraph.\r\n */\r\n getSubgraphDistanceMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adja = this.getSubgraphAdjacencyMatrix(vertexIds);\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of the graph.\r\n *\r\n * @returns {Array[]} The adjancency list of the graph.\r\n */\r\n getAdjacencyList() {\r\n let length = this.vertices.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = [];\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(this.vertices[i].id, this.vertices[j].id)) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency list of the subgraph.\r\n */\r\n getSubgraphAdjacencyList(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = Array();\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Returns an array containing the edge ids of bridges. A bridge splits the graph into multiple components when removed.\r\n *\r\n * @returns {Number[]} An array containing the edge ids of the bridges.\r\n */\r\n getBridges() {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n let disc = new Array(length);\r\n let low = new Array(length);\r\n let parent = new Array(length);\r\n let adj = this.getAdjacencyList();\r\n let outBridges = Array();\r\n\r\n visited.fill(false);\r\n parent.fill(null);\r\n this._time = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (!visited[i]) {\r\n this._bridgeDfs(i, visited, disc, low, parent, adj, outBridges);\r\n }\r\n }\r\n\r\n return outBridges;\r\n }\r\n\r\n /**\r\n * Traverses the graph in breadth-first order.\r\n *\r\n * @param {Number} startVertexId The id of the starting vertex.\r\n * @param {Function} callback The callback function to be called on every vertex.\r\n */\r\n traverseBF(startVertexId, callback) {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n\r\n visited.fill(false);\r\n\r\n var queue = [startVertexId];\r\n\r\n while (queue.length > 0) {\r\n // JavaScripts shift() is O(n) ... bad JavaScript, bad!\r\n let u = queue.shift();\r\n let vertex = this.vertices[u];\r\n\r\n callback(vertex);\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n let v = vertex.neighbours[i];\r\n if (!visited[v]) {\r\n visited[v] = true;\r\n queue.push(v);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the depth of a subtree in the direction opposite to the vertex specified as the parent vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId The id of a neighbouring vertex.\r\n * @returns {Number} The depth of the sub-tree.\r\n */\r\n getTreeDepth(vertexId, parentVertexId) {\r\n if (vertexId === null || parentVertexId === null) {\r\n return 0;\r\n }\r\n\r\n let neighbours = this.vertices[vertexId].getSpanningTreeNeighbours(parentVertexId);\r\n let max = 0;\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n let childId = neighbours[i];\r\n let d = this.getTreeDepth(childId, vertexId);\r\n\r\n if (d > max) {\r\n max = d;\r\n }\r\n }\r\n\r\n return max + 1;\r\n }\r\n\r\n /**\r\n * Traverse a sub-tree in the graph.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId A neighbouring vertex.\r\n * @param {Function} callback The callback function that is called with each visited as an argument.\r\n * @param {Number} [maxDepth=999999] The maximum depth of the recursion.\r\n * @param {Boolean} [ignoreFirst=false] Whether or not to ignore the starting vertex supplied as vertexId in the callback.\r\n * @param {Number} [depth=1] The current depth in the tree.\r\n * @param {Uint8Array} [visited=null] An array holding a flag on whether or not a node has been visited.\r\n */\r\n traverseTree(vertexId, parentVertexId, callback, maxDepth = 999999, ignoreFirst = false, depth = 1, visited = null) {\r\n if (visited === null) {\r\n visited = new Uint8Array(this.vertices.length);\r\n }\r\n\r\n if (depth > maxDepth + 1 || visited[vertexId] === 1) {\r\n return;\r\n }\r\n\r\n visited[vertexId] = 1;\r\n\r\n let vertex = this.vertices[vertexId];\r\n let neighbours = vertex.getNeighbours(parentVertexId);\r\n\r\n if (!ignoreFirst || depth > 1) {\r\n callback(vertex);\r\n }\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n this.traverseTree(neighbours[i], vertexId, callback, maxDepth, ignoreFirst, depth + 1, visited);\r\n }\r\n }\r\n\r\n /**\r\n * Positiones the (sub)graph using Kamada and Kawais algorithm for drawing general undirected graphs. https://pdfs.semanticscholar.org/b8d3/bca50ccc573c5cb99f7d201e8acce6618f04.pdf\r\n * There are undocumented layout parameters. They are undocumented for a reason, so be very careful.\r\n *\r\n * @param {Number[]} vertexIds An array containing vertexIds to be placed using the force based layout.\r\n * @param {Vector2} center The center of the layout.\r\n * @param {Number} startVertexId A vertex id. Should be the starting vertex - e.g. the first to be positioned and connected to a previously place vertex.\r\n * @param {Ring} ring The bridged ring associated with this force-based layout.\r\n */\r\n kkLayout(vertexIds, center, startVertexId, ring, bondLength,\r\n threshold = 0.1, innerThreshold = 0.1, maxIteration = 2000,\r\n maxInnerIteration = 50, maxEnergy = 1e9) {\r\n\r\n let edgeStrength = bondLength;\r\n\r\n // Add vertices that are directly connected to the ring\r\n var i = vertexIds.length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n var j = vertex.neighbours.length;\r\n }\r\n\r\n let matDist = this.getSubgraphDistanceMatrix(vertexIds);\r\n let length = vertexIds.length;\r\n\r\n // Initialize the positions. Place all vertices on a ring around the center\r\n let radius = MathHelper.polyCircumradius(500, length);\r\n let angle = MathHelper.centralAngle(length);\r\n let a = 0.0;\r\n let arrPositionX = new Float32Array(length);\r\n let arrPositionY = new Float32Array(length);\r\n let arrPositioned = Array(length);\r\n\r\n i = length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n if (!vertex.positioned) {\r\n arrPositionX[i] = center.x + Math.cos(a) * radius;\r\n arrPositionY[i] = center.y + Math.sin(a) * radius;\r\n } else {\r\n arrPositionX[i] = vertex.position.x;\r\n arrPositionY[i] = vertex.position.y;\r\n }\r\n arrPositioned[i] = vertex.positioned;\r\n a += angle;\r\n }\r\n\r\n // Create the matrix containing the lengths\r\n let matLength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matLength[i] = new Array(length);\r\n var j = length;\r\n while (j--) {\r\n matLength[i][j] = bondLength * matDist[i][j];\r\n }\r\n }\r\n\r\n // Create the matrix containing the spring strenghts\r\n let matStrength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matStrength[i] = Array(length);\r\n var j = length;\r\n while (j--) {\r\n matStrength[i][j] = edgeStrength * Math.pow(matDist[i][j], -2.0);\r\n }\r\n }\r\n\r\n // Create the matrix containing the energies\r\n let matEnergy = Array(length);\r\n let arrEnergySumX = new Float32Array(length);\r\n let arrEnergySumY = new Float32Array(length);\r\n i = length;\r\n while (i--) {\r\n matEnergy[i] = Array(length);\r\n }\r\n\r\n i = length;\r\n let ux, uy, dEx, dEy, vx, vy, denom;\r\n\r\n while (i--) {\r\n ux = arrPositionX[i];\r\n uy = arrPositionY[i];\r\n dEx = 0.0;\r\n dEy = 0.0;\r\n let j = length;\r\n while (j--) {\r\n if (i === j) {\r\n continue;\r\n }\r\n vx = arrPositionX[j];\r\n vy = arrPositionY[j];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n matEnergy[i][j] = [\r\n matStrength[i][j] * ((ux - vx) - matLength[i][j] * (ux - vx) * denom),\r\n matStrength[i][j] * ((uy - vy) - matLength[i][j] * (uy - vy) * denom)\r\n ];\r\n matEnergy[j][i] = matEnergy[i][j];\r\n dEx += matEnergy[i][j][0];\r\n dEy += matEnergy[i][j][1];\r\n }\r\n arrEnergySumX[i] = dEx;\r\n arrEnergySumY[i] = dEy;\r\n }\r\n\r\n // Utility functions, maybe inline them later\r\n let energy = function (index) {\r\n return [arrEnergySumX[index] * arrEnergySumX[index] + arrEnergySumY[index] * arrEnergySumY[index], arrEnergySumX[index], arrEnergySumY[index]];\r\n };\r\n\r\n let highestEnergy = function () {\r\n let maxEnergy = 0.0;\r\n let maxEnergyId = 0;\r\n let maxDEX = 0.0;\r\n let maxDEY = 0.0;\r\n\r\n i = length;\r\n while (i--) {\r\n let [delta, dEX, dEY] = energy(i);\r\n\r\n if (delta > maxEnergy && arrPositioned[i] === false) {\r\n maxEnergy = delta;\r\n maxEnergyId = i;\r\n maxDEX = dEX;\r\n maxDEY = dEY;\r\n }\r\n }\r\n\r\n return [maxEnergyId, maxEnergy, maxDEX, maxDEY];\r\n };\r\n\r\n let update = function (index, dEX, dEY) {\r\n let dxx = 0.0;\r\n let dyy = 0.0;\r\n let dxy = 0.0;\r\n let ux = arrPositionX[index];\r\n let uy = arrPositionY[index];\r\n let arrL = matLength[index];\r\n let arrK = matStrength[index];\r\n\r\n i = length;\r\n while (i--) {\r\n if (i === index) {\r\n continue;\r\n }\r\n\r\n let vx = arrPositionX[i];\r\n let vy = arrPositionY[i];\r\n let l = arrL[i];\r\n let k = arrK[i];\r\n let m = (ux - vx) * (ux - vx);\r\n let denom = 1.0 / Math.pow(m + (uy - vy) * (uy - vy), 1.5);\r\n\r\n dxx += k * (1 - l * (uy - vy) * (uy - vy) * denom);\r\n dyy += k * (1 - l * m * denom);\r\n dxy += k * (l * (ux - vx) * (uy - vy) * denom);\r\n }\r\n\r\n // Prevent division by zero\r\n if (dxx === 0) {\r\n dxx = 0.1;\r\n }\r\n\r\n if (dyy === 0) {\r\n dyy = 0.1;\r\n }\r\n\r\n if (dxy === 0) {\r\n dxy = 0.1;\r\n }\r\n\r\n let dy = (dEX / dxx + dEY / dxy);\r\n dy /= (dxy / dxx - dyy / dxy); // had to split this onto two lines because the syntax highlighter went crazy.\r\n let dx = -(dxy * dy + dEX) / dxx;\r\n\r\n arrPositionX[index] += dx;\r\n arrPositionY[index] += dy;\r\n\r\n // Update the energies\r\n let arrE = matEnergy[index];\r\n dEX = 0.0;\r\n dEY = 0.0;\r\n\r\n ux = arrPositionX[index];\r\n uy = arrPositionY[index];\r\n\r\n let vx, vy, prevEx, prevEy, denom;\r\n\r\n i = length;\r\n while (i--) {\r\n if (index === i) {\r\n continue;\r\n }\r\n vx = arrPositionX[i];\r\n vy = arrPositionY[i];\r\n // Store old energies\r\n prevEx = arrE[i][0];\r\n prevEy = arrE[i][1];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n dx = arrK[i] * ((ux - vx) - arrL[i] * (ux - vx) * denom);\r\n dy = arrK[i] * ((uy - vy) - arrL[i] * (uy - vy) * denom);\r\n\r\n arrE[i] = [dx, dy];\r\n dEX += dx;\r\n dEY += dy;\r\n arrEnergySumX[i] += dx - prevEx;\r\n arrEnergySumY[i] += dy - prevEy;\r\n }\r\n arrEnergySumX[index] = dEX;\r\n arrEnergySumY[index] = dEY;\r\n };\r\n\r\n // Setting up variables for the while loops\r\n let maxEnergyId = 0;\r\n let dEX = 0.0;\r\n let dEY = 0.0;\r\n let delta = 0.0;\r\n let iteration = 0;\r\n let innerIteration = 0;\r\n\r\n while (maxEnergy > threshold && maxIteration > iteration) {\r\n iteration++;\r\n [maxEnergyId, maxEnergy, dEX, dEY] = highestEnergy();\r\n delta = maxEnergy;\r\n innerIteration = 0;\r\n while (delta > innerThreshold && maxInnerIteration > innerIteration) {\r\n innerIteration++;\r\n update(maxEnergyId, dEX, dEY);\r\n [delta, dEX, dEY] = energy(maxEnergyId);\r\n }\r\n }\r\n\r\n i = length;\r\n while (i--) {\r\n let index = vertexIds[i];\r\n let vertex = this.vertices[index];\r\n vertex.position.x = arrPositionX[i];\r\n vertex.position.y = arrPositionY[i];\r\n vertex.positioned = true;\r\n vertex.forcePositioned = true;\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getBridges().\r\n */\r\n _bridgeDfs(u, visited, disc, low, parent, adj, outBridges) {\r\n visited[u] = true;\r\n disc[u] = low[u] = ++this._time;\r\n\r\n for (var i = 0; i < adj[u].length; i++) {\r\n let v = adj[u][i];\r\n\r\n if (!visited[v]) {\r\n parent[v] = u;\r\n\r\n this._bridgeDfs(v, visited, disc, low, parent, adj, outBridges);\r\n\r\n low[u] = Math.min(low[u], low[v]);\r\n\r\n // If low > disc, we have a bridge\r\n if (low[v] > disc[u]) {\r\n outBridges.push([u, v]);\r\n }\r\n } else if (v !== parent[u]) {\r\n low[u] = Math.min(low[u], disc[v]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the connected components of the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Set[]} Connected components as sets.\r\n */\r\n static getConnectedComponents(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let components = [];\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n let component = Array();\r\n visited[u] = true;\r\n component.push(u);\r\n count++;\r\n Graph._ccGetDfs(u, visited, adjacencyMatrix, component);\r\n if (component.length > 1) {\r\n components.push(component);\r\n }\r\n }\r\n }\r\n\r\n return components;\r\n }\r\n\r\n /**\r\n * Returns the number of connected components for the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of connected components of the supplied graph.\r\n */\r\n static getConnectedComponentCount(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n visited[u] = true;\r\n count++;\r\n Graph._ccCountDfs(u, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponentCount().\r\n */\r\n static _ccCountDfs(u, visited, adjacencyMatrix) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n Graph._ccCountDfs(v, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponents().\r\n */\r\n static _ccGetDfs(u, visited, adjacencyMatrix, component) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n component.push(v);\r\n Graph._ccGetDfs(v, visited, adjacencyMatrix, component);\r\n }\r\n }\r\n\r\n /**\r\n * Revert decay point value and update list of decay points\r\n * when edge isn't decay point -> change mark edge as decay point and add edge to decays list\r\n * when edge is decay point -> unmark edge as decay point and remove edgeId from list of decays\r\n * @param edgeId\r\n */\r\n revertEdgeDecayPoint(edgeId) {\r\n this.edges[edgeId].isDecay = !this.edges[edgeId].isDecay;\r\n this.edges[edgeId].isDecayAll = !this.edges[edgeId].isDecayAll;\r\n if (this.edges[edgeId].isDecay) {\r\n this.decays.push(edgeId);\r\n this.decaysAll.push(edgeId);\r\n } else {\r\n let index = this.decays.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decays.splice(index, 1);\r\n }\r\n index = this.decaysAll.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decaysAll.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.decays;\r\n }\r\n\r\n /**\r\n * Build block of SMILES based on decay points\r\n * DFS pass through graph\r\n * but the numbers are already setup in vertex.value.ringbonds array so no need to second pass of dfs\r\n */\r\n buildSmiles() {\r\n let smiles = [];\r\n this._polyketide = false;\r\n this.dfsSmilesInitialization();\r\n if (this.decays.length === 0) {\r\n this.startDfs(this.vertices[0], smiles);\r\n return {blockSmiles: smiles, sequence: '[0]', sequenceType: SequenceType.VALUES.OTHER, decays: this.decays, isPolyketide: this._polyketide};\r\n } else {\r\n this.dfsBuildSmilesStart(smiles);\r\n }\r\n this.dfsSmilesInitialization();\r\n this.dfsSmallStart();\r\n this._smallGraph.oneCyclic();\r\n this._smallGraph.dfsSequenceStart();\r\n\r\n let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence);\r\n\r\n return {\r\n blockSmiles: sequenceData.smiles,\r\n sequence: sequenceData.sequence,\r\n sequenceType: this._smallGraph.sequenceType + ((this._smallGraph.sequenceType === 'linear' || this._smallGraph.sequenceType === 'cyclic') && this._polyketide ? '-polyketide' : ''),\r\n decays: this.decays,\r\n isPolyketide: this._polyketide\r\n }\r\n }\r\n\r\n sortSequence(smiles, sequence) {\r\n let permutation = this.getSequencePermutation(sequence);\r\n let newSmiles = new Array(permutation.length).fill(null);\r\n for (let i = 0; i < permutation.length; ++i) {\r\n newSmiles[i] = smiles[permutation[i][0]];\r\n }\r\n\r\n let position = 0;\r\n let char = sequence.charAt(position);\r\n let newSequence = '';\r\n while (true) {\r\n switch (char) {\r\n case '0':\r\n case '1':\r\n case '2':\r\n case '3':\r\n case '4':\r\n case '5':\r\n case '6':\r\n case '7':\r\n case '8':\r\n case '9':\r\n let number = char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n while(!isNaN(char)) {\r\n number += char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n let j;\r\n for (j = 0; j < permutation.length; ++j) {\r\n if (permutation[j][0] === number) {\r\n newSequence += j;\r\n break;\r\n }\r\n }\r\n continue;\r\n default:\r\n newSequence += char;\r\n }\r\n\r\n ++position;\r\n if (position >= sequence.length) {\r\n break;\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n return {sequence: newSequence, smiles: newSmiles};\r\n }\r\n\r\n getSequencePermutation(sequence) {\r\n let re = /\\d+/g;\r\n let match = null;\r\n let permutation = [];\r\n while ((match = re.exec(sequence)) != null) {\r\n permutation.push(match);\r\n }\r\n return permutation;\r\n }\r\n\r\n dfsSmallStart() {\r\n this._smallGraph = new SmallGraph();\r\n for (let index = 0; index < this._startingVertexes.length; ++index) {\r\n this._smallGraph.addVertex(new Node(this._startingVertexes[index].component));\r\n this.first = this._startingVertexes[index];\r\n this.dfsSmall(this._startingVertexes[index], this._componentsIsPolyketide[index]);\r\n }\r\n }\r\n\r\n /**\r\n * Initialize graph for dfs\r\n * set for all vertices vertexState to NotFound\r\n */\r\n dfsSmilesInitialization() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n /**\r\n * Starting function for DFS\r\n * starts on decay points (on edge), so start on both side of edge\r\n * @param {Array} smiles output param, array of SMILES blocks (string)\r\n */\r\n dfsBuildSmilesStart(smiles) {\r\n this._cnt = 0;\r\n this._markComponent = false;\r\n this._startingVertexes = [];\r\n for (let i = 0; i < this.decays.length; ++i) {\r\n let edge = this.edges[this.decays[i]];\r\n this.markingComponents(this.startDfs(this.vertices[edge.sourceId], smiles));\r\n this.markingComponents(this.startDfs(this.vertices[edge.targetId], smiles));\r\n }\r\n }\r\n\r\n markingComponents(isPolyketyde) {\r\n if (this._markComponent) {\r\n this._cnt++;\r\n this._markComponent = false;\r\n this._componentsIsPolyketide.push(isPolyketyde);\r\n }\r\n }\r\n\r\n /**\r\n * Start DFS for build SMILES of blocks\r\n * @param {Vertex} vertex to start DFS\r\n * @param {Array} smiles output param, array od SMILES\r\n */\r\n startDfs(vertex, smiles) {\r\n let isPolyketide = new MutableBoolean(true);\r\n let decaysCounter = new MutableCounter();\r\n let vertexCounter = new MutableCounter();\r\n let through = [];\r\n let stackSmiles = [];\r\n this.first = vertex.id;\r\n this._isCyclic = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.dfsSmiles(vertex, stackSmiles, isPolyketide, decaysCounter, through, vertexCounter);\r\n if (decaysCounter.getValue() < 2 && isPolyketide.getValue() === true) {\r\n isPolyketide.setValue(through.every(vertex => vertex === 'O' || vertex === 'N') && vertexCounter.getValue() > 4);\r\n }\r\n if (this._isCyclic) {\r\n this.closedToNotFound();\r\n stackSmiles = [];\r\n this.dfsSmiles(vertex, stackSmiles, new MutableBoolean(true), new MutableCounter(), [], new MutableCounter(), -1, true);\r\n }\r\n this.closedToFullyClosed();\r\n\r\n stackSmiles = Graph.removeUnnecessaryParentheses(stackSmiles);\r\n let smile = Graph.removeUnnecessaryNumbers(stackSmiles.join(\"\"));\r\n if (smile.length !== 0) {\r\n smiles.push({smiles: smile, isPolyketide: isPolyketide.getValue()});\r\n if (isPolyketide.getValue() === true) {\r\n this._polyketide = true;\r\n }\r\n }\r\n return isPolyketide.getValue();\r\n }\r\n\r\n closedToNotFound() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n }\r\n\r\n closedToFullyClosed() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.FULLY_CLOSED;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * DFS for SMILES\r\n * @param {Vertex} vertex\r\n * @param {Array} stackSmiles output param\r\n * @param {MutableBoolean} isPolyketide\r\n * @param {MutableCounter} cntDecays\r\n * @param {Array} through\r\n * @param {MutableCounter} vertexCounter\r\n * @param lastVertexId last vertex id for setup digits\r\n * @param isSecondPass is second pass of dfs\r\n */\r\n dfsSmiles(vertex, stackSmiles, isPolyketide, cntDecays, through, vertexCounter, lastVertexId = -1, isSecondPass = false) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN && !isSecondPass && lastVertexId !== -1) {\r\n this._isCyclic = true;\r\n if (!vertex.digits.some(e => this.vertices[lastVertexId].digits.includes(e))) {\r\n vertex.digits.push(this._digitCounter);\r\n this.vertices[lastVertexId].digits.push(this._digitCounter);\r\n this._digitCounter++;\r\n }\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n if (vertex.value.element === 'H') {\r\n return;\r\n }\r\n\r\n if (this.first === vertex.id && vertex.value.element === \"C\" && isPolyketide.getValue()) {\r\n stackSmiles.push(\"O\");\r\n isPolyketide.setValue(false);\r\n }\r\n\r\n if (vertex.value.bracket) {\r\n stackSmiles.push(\"[\");\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n if (vertex.value.bracket.hcount > 0) {\r\n stackSmiles.push('H');\r\n if (vertex.value.bracket.hcount > 1) {\r\n stackSmiles.push(vertex.value.bracket.hcount);\r\n }\r\n }\r\n if (vertex.value.bracket.charge > 0) {\r\n stackSmiles.push('+');\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n } else if (vertex.value.bracket.charge < 0) {\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n }\r\n stackSmiles.push(\"]\");\r\n } else {\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n }\r\n vertexCounter.increment();\r\n\r\n if (isSecondPass) {\r\n stackSmiles.push(this.smilesNumbersAdd(vertex));\r\n }\r\n\r\n if (!this._markComponent) {\r\n this._startingVertexes.push(vertex);\r\n }\r\n vertex.component = this._cnt;\r\n this._markComponent = true;\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n if (edge.isDecayAll && lastVertexId !== nextVertex) {\r\n through.push(vertex.value.element);\r\n }\r\n if (edge.isDecay) {\r\n cntDecays.increment();\r\n if (vertex.value.element === \"C\" && vertex.id !== this.first && isPolyketide.getValue()) {\r\n stackSmiles.push(\"(\");\r\n stackSmiles.push(\"O\");\r\n stackSmiles.push(\")\");\r\n isPolyketide.setValue(false);\r\n }\r\n continue;\r\n }\r\n stackSmiles.push(\"(\");\r\n Graph.addBondTypeToStack(edge, stackSmiles);\r\n if (lastVertexId !== nextVertex) {\r\n this.dfsSmiles(this.vertices[nextVertex], stackSmiles, isPolyketide, cntDecays, through, vertexCounter, vertex.id, isSecondPass);\r\n }\r\n Graph.checkStack(stackSmiles);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSmall(vertex, isPolyketide) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n\r\n this._smallGraph.addNeighbour(vertex.component, this.vertices[Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId)].component, Direction.getProperValue(isPolyketide, vertex.value.element, vertex.id, this.first));\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n this.dfsSmall(this.vertices[nextVertex], isPolyketide);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n\r\n static printVertexValue(stackSmiles, vertex) {\r\n if (vertex.value.isPartOfAromaticRing) {\r\n stackSmiles.push(vertex.value.element.toLowerCase());\r\n } else {\r\n stackSmiles.push(vertex.value.element);\r\n }\r\n }\r\n\r\n /**\r\n * Remove numbers which is neighbours in SMILES notation -> need to perform in cyclic structures\r\n * @param {String} smiles SMILES\r\n * @return {String} repaired SMILES\r\n */\r\n static removeUnnecessaryNumbers(smiles) {\r\n if (smiles === null) {\r\n return '';\r\n }\r\n try {\r\n let numbers = this.getNumbers(smiles);\r\n for (let number of numbers) {\r\n let first = this.findFirst(smiles, number);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n let tmpRange = this.removeRangeLast(smiles, first, second, number);\r\n smiles = this.repairSmiles(smiles, tmpRange, first, second, number);\r\n }\r\n return smiles;\r\n } catch (ex) {\r\n return smiles;\r\n }\r\n }\r\n\r\n /**\r\n * Remove unnecessary numbers from SMILES\r\n * @param {String} smiles\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {*}\r\n */\r\n static removeNumbers(smiles, first, second, number) {\r\n if (number > 9) {\r\n let numLength = number.toString().length;\r\n smiles = smiles.slice(0, first - 1) + smiles.slice(first + numLength);\r\n return smiles.slice(0, second - 2 - numLength) + smiles.slice(second - 1);\r\n } else {\r\n smiles = smiles.slice(0, first) + smiles.slice(first + 1);\r\n return smiles.slice(0, second - 1) + smiles.slice(second);\r\n }\r\n }\r\n\r\n /**\r\n * Reapair SMILES\r\n * @param {String} smiles\r\n * @param {String} tmpRange\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {String|*}\r\n */\r\n static repairSmiles(smiles, tmpRange, first, second, number) {\r\n let pattern = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])$\");\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let patternOrg = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])\");\r\n if (patternOrg.test(tmpRange)) {\r\n return smiles;\r\n }\r\n\r\n while (tmpRange.length !== 0) {\r\n if (tmpRange[0] === '(') {\r\n tmpRange = tmpRange.substring(1);\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let leftBrackets = 1;\r\n let rightBrackets = 0;\r\n while (leftBrackets !== rightBrackets) {\r\n switch (tmpRange[0]) {\r\n case '(':\r\n leftBrackets++;\r\n break;\r\n case ')':\r\n rightBrackets++;\r\n break;\r\n }\r\n if (\"\" === tmpRange) {\r\n return smiles;\r\n }\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n return this.repairSmiles(smiles, tmpRange, first, second, number);\r\n } else {\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Substring in range and remove last Organic Subset\r\n * @param smiles\r\n * @param first\r\n * @param second\r\n * @param number\r\n * @return {string}\r\n */\r\n static removeRangeLast(smiles, first, second, number) {\r\n if (number > 9) {\r\n return smiles.substring(first + number.toString().length, second - 1);\r\n } else {\r\n return smiles.substring(first + 1, second);\r\n }\r\n }\r\n\r\n /**\r\n * Get numbers from SMILES\r\n * @param smiles\r\n * @return {Set}\r\n */\r\n static getNumbers(smiles) {\r\n let numbers = new Set();\r\n for (let index = 0; index < smiles.length; ++index) {\r\n if (!isNaN(smiles[index])) {\r\n numbers.add(smiles[index]);\r\n } else if (smiles[index] === '%') {\r\n index++;\r\n let num = \"\";\r\n while (!isNaN(smiles[index])) {\r\n num += smiles[index];\r\n index++;\r\n if (index >= smiles.length) {\r\n break;\r\n }\r\n }\r\n index--;\r\n numbers.add(num);\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * return index of first occurrence number\r\n * @param smiles\r\n * @param number\r\n * @return {number}\r\n */\r\n static findFirst(smiles, number) {\r\n return smiles.indexOf(number);\r\n }\r\n\r\n /**\r\n * return index of first occurrence number from index + 1\r\n * @param smiles\r\n * @param from range no including this point (from, Infinity) = [from + 1, Infinity)\r\n * @param number\r\n * @return {*}\r\n */\r\n static findSecond(smiles, from, number) {\r\n let result = smiles.indexOf(number, from);\r\n if (result === -1) {\r\n throw \"Not Found\";\r\n }\r\n return result;\r\n }\r\n\r\n\r\n smilesNumbersAdd(vertex) {\r\n let numbers = '';\r\n for (let i = 0; i < vertex.digits.length; ++i) {\r\n let num = vertex.digits[i];\r\n if (this._printedDigits.some(e => e === num)) {\r\n let nextVertex = this.vertices.find(e => e.digits.includes(num) && e.id !== vertex.id);\r\n let intersection = vertex.edges.filter(element => nextVertex.edges.includes(element));\r\n\r\n if (intersection.length > 0) {\r\n let bond = this.edges[intersection[0]].bondType;\r\n if (bond !== '-') {\r\n numbers += bond;\r\n }\r\n }\r\n }\r\n\r\n this._printedDigits.push(num);\r\n let numString = num.toString();\r\n if (numString.length === 1) {\r\n numbers += numString;\r\n } else {\r\n numbers += '%' + numString;\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * Return other vertex id then the actual vertex id\r\n * when vertexId === sourceId return targetId\r\n * when vertexId === targetId return sourceId\r\n * @param {Number} vertexId actual vertex id\r\n * @param {Number} sourceId source vertex id\r\n * @param {Number} targetId target vertex id\r\n * @return {Number}\r\n */\r\n static getProperVertex(vertexId, sourceId, targetId) {\r\n if (vertexId === sourceId) return targetId;\r\n else return sourceId;\r\n }\r\n\r\n static repairNumbers(smiles) {\r\n try {\r\n let numbers = Array.from(this.getNumbers(smiles));\r\n numbers.sort(function (a, b) {\r\n return b - a\r\n });\r\n\r\n let index = 1;\r\n for (let number of numbers) {\r\n if (index === number) {\r\n continue;\r\n }\r\n let first = this.findFirst(smiles, number);\r\n if (number > 9) {\r\n smiles = smiles.slice(0, first - 1) + index + smiles.slice(first + number.toString().length);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second - 1) + index + smiles.slice(second + number.toString().length);\r\n } else {\r\n smiles = smiles.slice(0, first) + index + smiles.slice(first + 1);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second) + index + smiles.slice(second + 1);\r\n }\r\n index++;\r\n }\r\n } catch (e) {\r\n return smiles;\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from SMILES\r\n * example CCC(CC)(C) -> CCC(CC)C\r\n * example C(=O)C(C(C)) -> C(=O)CCC\r\n * @param {Array} stackRight\r\n * @return {Array}\r\n */\r\n static removeUnnecessaryParentheses(stackRight) {\r\n if (stackRight.length === 0) return [];\r\n let stackLeft = [], lastLiteral = \"\", literal = \"\";\r\n while (stackRight.length > 0) {\r\n literal = stackRight.shift();\r\n if ((\")\".localeCompare(literal) === 0 && \")\".localeCompare(lastLiteral) === 0)) {\r\n Graph.removeParentheses(stackLeft, false, literal);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n lastLiteral = literal;\r\n }\r\n\r\n literal = stackLeft.pop();\r\n if ((\")\".localeCompare(literal) === 0 && stackRight.length === 0)) {\r\n Graph.removeParentheses(stackLeft);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n return stackLeft;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from stack\r\n * go through stack and when find proper closing bracket,\r\n * then remove it and push back removed data when searching in stack\r\n * @param {Array} stack with unnecessary parentheses to remove\r\n * @param {Boolean} end treat with situation when \")\" is last character of stack -> end = true, else where end = false\r\n * @param {String} literal, when end = false, need to pop from stack and at the end add literal back to stack\r\n */\r\n static removeParentheses(stack, end = true, literal = \"\") {\r\n let stackTmp = [];\r\n let leftBraces = 0, rightBraces = 1;\r\n if (!end) {\r\n stack.pop();\r\n }\r\n while (true) {\r\n let lit = stack.pop();\r\n if (\"(\".localeCompare(lit) === 0) {\r\n leftBraces++;\r\n } else if (\")\".localeCompare(lit) === 0) {\r\n rightBraces++;\r\n }\r\n if (leftBraces === rightBraces) {\r\n Graph.moveAllValuesInStackToAnotherStack(stackTmp, stack);\r\n if (!end) {\r\n stack.push(literal);\r\n }\r\n break;\r\n }\r\n stackTmp.push(lit);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all values from stackSource and push it to stackDestination\r\n * @param {Array} stackSource stack to remove values\r\n * @param {Array} stackDestination stack to add values from stackSource\r\n */\r\n static moveAllValuesInStackToAnotherStack(stackSource, stackDestination) {\r\n while (stackSource.length > 0) {\r\n stackDestination.push(stackSource.pop());\r\n }\r\n }\r\n\r\n /**\r\n * Check last value of stack\r\n * if it one of (, -, = or # then remove all characters in stack to first ( from the end of stack\r\n * elsewhere add ) to stack\r\n * @param {Array} stackSmiles\r\n */\r\n static checkStack(stackSmiles) {\r\n switch (stackSmiles[stackSmiles.length - 1]) {\r\n case \"(\":\r\n case \"-\":\r\n case \"=\":\r\n case \"#\":\r\n Graph.removeAllFromStackToFirstLeftBrace(stackSmiles);\r\n break;\r\n default:\r\n stackSmiles.push(\")\");\r\n }\r\n }\r\n\r\n /**\r\n * Remove all characters from stack to first \"(\"\r\n * @param {Array} stackSmiles\r\n */\r\n static removeAllFromStackToFirstLeftBrace(stackSmiles) {\r\n let literal = stackSmiles.pop();\r\n while (literal !== \"(\") {\r\n if (stackSmiles.length === 0) break;\r\n literal = stackSmiles.pop();\r\n }\r\n }\r\n\r\n /**\r\n * Add bond type to stack\r\n * if edge have = or # bond type add it to stack\r\n * @param {Edge} edge\r\n * @param {Array} stackSmiles\r\n */\r\n static addBondTypeToStack(edge, stackSmiles) {\r\n if (edge.bondType === \"=\" || edge.bondType === \"#\") {\r\n stackSmiles.push(edge.bondType);\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Graph;\r\n","//@ts-check\r\nconst Vector2 = require('./Vector2')\r\n\r\n/** \r\n * A class representing a line.\r\n * \r\n * @property {Vector2} from The Vector2 defining the start of the line.\r\n * @property {Vector2} to The Vector2 defining the end of the line.\r\n * @property {String} elementFrom The element symbol associated with the start of the line.\r\n * @property {String} elementTo The element symbol associated with the end of the line.\r\n * @property {Boolean} chiralFrom A boolean indicating whether or not the source atom is a chiral center.\r\n * @property {Boolean} chiralTo A boolean indicating whether or tno the target atom is a chiral center.\r\n */\r\nclass Line {\r\n /**\r\n * The constructor for the class Line.\r\n *\r\n * @param {Vector2} [from=new Vector2(0, 0)] A vector marking the beginning of the line.\r\n * @param {Vector2} [to=new Vector2(0, 0)] A vector marking the end of the line.\r\n * @param {string} [elementFrom=null] A one-letter representation of the element associated with the vector marking the beginning of the line.\r\n * @param {string} [elementTo=null] A one-letter representation of the element associated with the vector marking the end of the line.\r\n * @param {Boolean} [chiralFrom=false] Whether or not the from atom is a chiral center.\r\n * @param {Boolean} [chiralTo=false] Whether or not the to atom is a chiral center.\r\n * @param {Boolean} [isDecayPoint=false] Whether or not the edge is a decay point\r\n */\r\n constructor(from = new Vector2(0,0), to = new Vector2(0, 0), elementFrom = null, elementTo = null, chiralFrom = false, chiralTo = false, isDecayPoint = false) {\r\n this.from = from;\r\n this.to = to;\r\n this.elementFrom = elementFrom;\r\n this.elementTo = elementTo;\r\n this.chiralFrom = chiralFrom;\r\n this.chiralTo = chiralTo;\r\n this.isDecayPoint = isDecayPoint;\r\n }\r\n\r\n /**\r\n * Clones this line and returns the clone.\r\n *\r\n * @returns {Line} A clone of this line.\r\n */\r\n clone() {\r\n return new Line(this.from.clone(), this.to.clone(), this.elementFrom, this.elementTo);\r\n }\r\n\r\n /**\r\n * Returns the length of this line.\r\n *\r\n * @returns {Number} The length of this line.\r\n */\r\n getLength() {\r\n return Math.sqrt(Math.pow(this.to.x - this.from.x, 2) + \r\n Math.pow(this.to.y - this.from.y, 2));\r\n }\r\n\r\n\r\n /**\r\n * Returns the angle of the line in relation to the coordinate system (the x-axis).\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n // Get the angle between the line and the x-axis\r\n let diff = Vector2.subtract(this.getRightVector(), this.getLeftVector());\r\n return diff.angle();\r\n }\r\n\r\n /**\r\n * Returns the right vector (the vector with the larger x value).\r\n *\r\n * @returns {Vector2} The right vector.\r\n */\r\n getRightVector() {\r\n // Return the vector with the larger x value (the right one)\r\n if (this.from.x < this.to.x) {\r\n return this.to;\r\n } else {\r\n return this.from;\r\n }\r\n }\r\n \r\n /**\r\n * Returns the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {Vector2} The left vector.\r\n */\r\n getLeftVector() {\r\n // Return the vector with the smaller x value (the left one)\r\n if (this.from.x < this.to.x) {\r\n return this.from;\r\n } else {\r\n return this.to;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the right vector (the vector with the larger x value).\r\n *\r\n * @returns {String} The element associated with the right vector.\r\n */\r\n getRightElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementTo;\r\n } else {\r\n return this.elementFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {String} The element associated with the left vector.\r\n */\r\n getLeftElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementFrom;\r\n } else {\r\n return this.elementTo;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the right vector (the vector with the larger x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the right vector is a chiral center.\r\n */\r\n getRightChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralTo;\r\n } else {\r\n return this.chiralFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the left vector (the vector with the smaller x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the left vector is a chiral center.\r\n */\r\n getLeftChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralFrom;\r\n } else {\r\n return this.chiralTo;\r\n }\r\n }\r\n\r\n /**\r\n * Set the value of the right vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setRightVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.to.x = x;\r\n this.to.y = y;\r\n } else {\r\n this.from.x = x;\r\n this.from.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Set the value of the left vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setLeftVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.from.x = x;\r\n this.from.y = y;\r\n } else {\r\n this.to.x = x;\r\n this.to.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this line to be aligned with the x-axis. The center of rotation is the left vector.\r\n *\r\n * @returns {Line} This line.\r\n */\r\n rotateToXAxis() {\r\n let left = this.getLeftVector();\r\n \r\n this.setRightVector(left.x + this.getLength(), left.y);\r\n \r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate the line by a given value (in radians). The center of rotation is the left vector.\r\n *\r\n * @param {Number} theta The angle (in radians) to rotate the line.\r\n * @returns {Line} This line.\r\n */\r\n rotate(theta) {\r\n let l = this.getLeftVector();\r\n let r = this.getRightVector();\r\n let sinTheta = Math.sin(theta);\r\n let cosTheta = Math.cos(theta);\r\n\r\n let x = cosTheta * (r.x - l.x) - sinTheta * (r.y - l.y) + l.x;\r\n let y = sinTheta * (r.x - l.x) - cosTheta * (r.y - l.y) + l.y;\r\n \r\n this.setRightVector(x, y);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"from\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenFrom(by) {\r\n let f = Vector2.subtract(this.to, this.from);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.from.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"to\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenTo(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.to.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shorten the right side.\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenRight(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenTo(by);\r\n } else {\r\n this.shortenFrom(by);\r\n }\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Shorten the left side.\r\n * \r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenLeft(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenFrom(by);\r\n } else {\r\n this.shortenTo(by);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from both directions by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shorten(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by / 2.0);\r\n \r\n this.to.add(f);\r\n this.from.subtract(f);\r\n\r\n return this;\r\n }\r\n}\r\n\r\nmodule.exports = Line;","/** \r\n * A static class containing helper functions for math-related tasks. \r\n */\r\nclass MathHelper {\r\n /**\r\n * Rounds a value to a given number of decimals.\r\n *\r\n * @static\r\n * @param {Number} value A number.\r\n * @param {Number} decimals The number of decimals.\r\n * @returns {Number} A number rounded to a given number of decimals.\r\n */\r\n static round(value, decimals) {\r\n decimals = decimals ? decimals : 1;\r\n return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);\r\n }\r\n\r\n /**\r\n * Returns the means of the angles contained in an array. In radians.\r\n *\r\n * @static\r\n * @param {Number[]} arr An array containing angles (in radians).\r\n * @returns {Number} The mean angle in radians.\r\n */\r\n static meanAngle(arr) {\r\n let sin = 0.0;\r\n let cos = 0.0;\r\n \r\n for (var i = 0; i < arr.length; i++) {\r\n sin += Math.sin(arr[i]);\r\n cos += Math.cos(arr[i]);\r\n }\r\n\r\n return Math.atan2(sin / arr.length, cos / arr.length);\r\n }\r\n\r\n /**\r\n * Returns the inner angle of a n-sided regular polygon.\r\n *\r\n * @static\r\n * @param {Number} n Number of sides of a regular polygon.\r\n * @returns {Number} The inner angle of a given regular polygon.\r\n */\r\n static innerAngle(n) {\r\n return MathHelper.toRad((n - 2) * 180 / n);\r\n }\r\n\r\n /**\r\n * Returns the circumradius of a n-sided regular polygon with a given side-length.\r\n *\r\n * @static\r\n * @param {Number} s The side length of the regular polygon.\r\n * @param {Number} n The number of sides.\r\n * @returns {Number} The circumradius of the regular polygon.\r\n */\r\n static polyCircumradius(s, n) {\r\n return s / (2 * Math.sin(Math.PI / n));\r\n }\r\n\r\n /**\r\n * Returns the apothem of a regular n-sided polygon based on its radius.\r\n *\r\n * @static\r\n * @param {Number} r The radius.\r\n * @param {Number} n The number of edges of the regular polygon.\r\n * @returns {Number} The apothem of a n-sided polygon based on its radius.\r\n */\r\n static apothem(r, n) {\r\n return r * Math.cos(Math.PI / n);\r\n }\r\n\r\n static apothemFromSideLength(s, n) {\r\n let r = MathHelper.polyCircumradius(s, n);\r\n \r\n return MathHelper.apothem(r, n);\r\n }\r\n\r\n /**\r\n * The central angle of a n-sided regular polygon. In radians.\r\n *\r\n * @static\r\n * @param {Number} n The number of sides of the regular polygon.\r\n * @returns {Number} The central angle of the n-sided polygon in radians.\r\n */\r\n static centralAngle(n) {\r\n return MathHelper.toRad(360 / n);\r\n }\r\n\r\n /**\r\n * Convertes radians to degrees.\r\n *\r\n * @static\r\n * @param {Number} rad An angle in radians.\r\n * @returns {Number} The angle in degrees.\r\n */\r\n static toDeg(rad) {\r\n return rad * MathHelper.degFactor;\r\n }\r\n\r\n /**\r\n * Converts degrees to radians.\r\n *\r\n * @static\r\n * @param {Number} deg An angle in degrees.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static toRad(deg) {\r\n return deg * MathHelper.radFactor;\r\n }\r\n\r\n /**\r\n * Returns the parity of the permutation (1 or -1)\r\n * @param {(Array|Uint8Array)} arr An array containing the permutation.\r\n * @returns {Number} The parity of the permutation (1 or -1), where 1 means even and -1 means odd.\r\n */\r\n static parityOfPermutation(arr) {\r\n let visited = new Uint8Array(arr.length);\r\n let evenLengthCycleCount = 0;\r\n\r\n let traverseCycle = function(i, cycleLength = 0) {\r\n if (visited[i] === 1) {\r\n return cycleLength;\r\n }\r\n\r\n cycleLength++;\r\n\r\n visited[i] = 1;\r\n return traverseCycle(arr[i], cycleLength);\r\n }\r\n\r\n for (var i = 0; i < arr.length; i++) {\r\n if (visited[i] === 1) {\r\n continue;\r\n }\r\n\r\n let cycleLength = traverseCycle(i);\r\n evenLengthCycleCount += (1 - cycleLength % 2);\r\n }\r\n\r\n return evenLengthCycleCount % 2 ? -1 : 1;\r\n }\r\n\r\n /** The factor to convert degrees to radians. */\r\n static get radFactor() {\r\n return Math.PI / 180.0;\r\n }\r\n\r\n /** The factor to convert radians to degrees. */\r\n static get degFactor() {\r\n return 180.0 / Math.PI;\r\n }\r\n\r\n /** Two times PI. */\r\n static get twoPI() {\r\n return 2.0 * Math.PI;\r\n }\r\n}\r\n\r\nmodule.exports = MathHelper;","/**\r\n *@property {boolean} value is boolean\r\n */\r\nclass MutableBoolean {\r\n\r\n /**\r\n * @param {boolean} value\r\n */\r\n constructor(value) {\r\n this.value = value;\r\n }\r\n\r\n setValue(value) {\r\n this.value = value;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableBoolean;\r\n","/**\r\n * @param {Number} value\r\n */\r\nclass MutableCounter {\r\n\r\n constructor() {\r\n this.value = 0;\r\n }\r\n\r\n increment() {\r\n this.value++;\r\n }\r\n\r\n reset() {\r\n this.value = 0;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableCounter;\r\n","\r\nclass Neighbour {\r\n\r\n constructor(neighbour, direction) {\r\n this.neighbour = neighbour;\r\n this.direction = direction;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Neighbour;\r\n","//@ts-check\r\nconst VertexState = require(\"./VertexState\");\r\n\r\nclass Node {\r\n\r\n constructor(id) {\r\n this.id = id;\r\n this.neighbours = [];\r\n this.onRing = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n\r\n addNeighbour(neighbour) {\r\n this.neighbours.push(neighbour);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Node;\r\n","// WHEN REPLACING, CHECK FOR:\r\n// KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\nmodule.exports = (function () {\r\n \"use strict\";\r\n\r\n /*\r\n * Generated by PEG.js 0.10.0.\r\n *\r\n * http://pegjs.org/\r\n */\r\n\r\n function peg$subclass(child, parent) {\r\n function ctor() {\r\n this.constructor = child;\r\n }\r\n ctor.prototype = parent.prototype;\r\n child.prototype = new ctor();\r\n }\r\n\r\n function peg$SyntaxError(message, expected, found, location) {\r\n this.message = message;\r\n this.expected = expected;\r\n this.found = found;\r\n this.location = location;\r\n this.name = \"SyntaxError\";\r\n\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(this, peg$SyntaxError);\r\n }\r\n }\r\n\r\n peg$subclass(peg$SyntaxError, Error);\r\n\r\n peg$SyntaxError.buildMessage = function (expected, found) {\r\n var DESCRIBE_EXPECTATION_FNS = {\r\n literal: function (expectation) {\r\n return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";\r\n },\r\n\r\n \"class\": function (expectation) {\r\n var escapedParts = \"\",\r\n i;\r\n\r\n for (i = 0; i < expectation.parts.length; i++) {\r\n escapedParts += expectation.parts[i] instanceof Array ?\r\n classEscape(expectation.parts[i][0]) + \"-\" + classEscape(expectation.parts[i][1]) :\r\n classEscape(expectation.parts[i]);\r\n }\r\n\r\n return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";\r\n },\r\n\r\n any: function (expectation) {\r\n return \"any character\";\r\n },\r\n\r\n end: function (expectation) {\r\n return \"end of input\";\r\n },\r\n\r\n other: function (expectation) {\r\n return expectation.description;\r\n }\r\n };\r\n\r\n function hex(ch) {\r\n return ch.charCodeAt(0).toString(16).toUpperCase();\r\n }\r\n\r\n function literalEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function classEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\\]/g, '\\\\]')\r\n .replace(/\\^/g, '\\\\^')\r\n .replace(/-/g, '\\\\-')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function describeExpectation(expectation) {\r\n return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\r\n }\r\n\r\n function describeExpected(expected) {\r\n var descriptions = new Array(expected.length),\r\n i, j;\r\n\r\n for (i = 0; i < expected.length; i++) {\r\n descriptions[i] = describeExpectation(expected[i]);\r\n }\r\n\r\n descriptions.sort();\r\n\r\n if (descriptions.length > 0) {\r\n for (i = 1, j = 1; i < descriptions.length; i++) {\r\n if (descriptions[i - 1] !== descriptions[i]) {\r\n descriptions[j] = descriptions[i];\r\n j++;\r\n }\r\n }\r\n descriptions.length = j;\r\n }\r\n\r\n switch (descriptions.length) {\r\n case 1:\r\n return descriptions[0];\r\n\r\n case 2:\r\n return descriptions[0] + \" or \" + descriptions[1];\r\n\r\n default:\r\n return descriptions.slice(0, -1).join(\", \") +\r\n \", or \" +\r\n descriptions[descriptions.length - 1];\r\n }\r\n }\r\n\r\n function describeFound(found) {\r\n return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";\r\n }\r\n\r\n return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\r\n };\r\n\r\n function peg$parse(input, options) {\r\n options = options !== void 0 ? options : {};\r\n\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n var nOpenParentheses = input.split('(').length - 1;\r\n var nCloseParentheses = input.split(')').length - 1;\r\n\r\n if (nOpenParentheses !== nCloseParentheses) {\r\n throw peg$buildSimpleError('The number of opening parentheses does not match the number of closing parentheses.', 0);\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n var peg$FAILED = {},\r\n\r\n peg$startRuleFunctions = {\r\n chain: peg$parsechain\r\n },\r\n peg$startRuleFunction = peg$parsechain,\r\n\r\n peg$c0 = function (s) {\r\n var branches = [];\r\n var rings = [];\r\n\r\n for (var i = 0; i < s[1].length; i++) {\r\n branches.push(s[1][i]);\r\n }\r\n\r\n\r\n for (var i = 0; i < s[2].length; i++) {\r\n var bond = (s[2][i][0]) ? s[2][i][0] : '-';\r\n rings.push({\r\n 'bond': bond,\r\n 'id': s[2][i][1]\r\n });\r\n }\r\n\r\n for (var i = 0; i < s[3].length; i++) {\r\n branches.push(s[3][i]);\r\n }\r\n\r\n for (var i = 0; i < s[6].length; i++) {\r\n branches.push(s[6][i]);\r\n }\r\n\r\n return {\r\n 'atom': s[0],\r\n 'isBracket': s[0].element ? true : false,\r\n 'branches': branches,\r\n 'branchCount': branches.length,\r\n 'ringbonds': rings,\r\n 'ringbondCount': rings.length,\r\n 'bond': s[4] ? s[4] : '-',\r\n 'next': s[5],\r\n 'hasNext': s[5] ? true : false\r\n }\r\n\r\n return s;\r\n },\r\n peg$c1 = \"(\",\r\n peg$c2 = peg$literalExpectation(\"(\", false),\r\n peg$c3 = \")\",\r\n peg$c4 = peg$literalExpectation(\")\", false),\r\n peg$c5 = function (b) {\r\n var bond = (b[1]) ? b[1] : '-';\r\n b[2].branchBond = bond;\r\n return b[2]\r\n },\r\n peg$c6 = function (a) {\r\n return a;\r\n },\r\n peg$c7 = /^[\\-=#$:\\/\\\\.]/,\r\n peg$c8 = peg$classExpectation([\"-\", \"=\", \"#\", \"$\", \":\", \"/\", \"\\\\\", \".\"], false, false),\r\n peg$c9 = function (b) {\r\n return b;\r\n },\r\n peg$c10 = \"[\",\r\n peg$c11 = peg$literalExpectation(\"[\", false),\r\n peg$c12 = \"se\",\r\n peg$c13 = peg$literalExpectation(\"se\", false),\r\n peg$c14 = \"as\",\r\n peg$c15 = peg$literalExpectation(\"as\", false),\r\n peg$c16 = \"]\",\r\n peg$c17 = peg$literalExpectation(\"]\", false),\r\n peg$c18 = function (b) {\r\n return {\r\n 'isotope': b[1],\r\n 'element': b[2],\r\n 'chirality': b[3],\r\n 'hcount': b[4],\r\n 'charge': b[5],\r\n 'class': b[6]\r\n }\r\n },\r\n peg$c19 = \"B\",\r\n peg$c20 = peg$literalExpectation(\"B\", false),\r\n peg$c21 = \"r\",\r\n peg$c22 = peg$literalExpectation(\"r\", false),\r\n peg$c23 = \"C\",\r\n peg$c24 = peg$literalExpectation(\"C\", false),\r\n peg$c25 = \"l\",\r\n peg$c26 = peg$literalExpectation(\"l\", false),\r\n peg$c27 = /^[NOPSFI]/,\r\n peg$c28 = peg$classExpectation([\"N\", \"O\", \"P\", \"S\", \"F\", \"I\"], false, false),\r\n peg$c29 = function (o) {\r\n if (o.length > 1) return o.join('');\r\n return o;\r\n },\r\n peg$c30 = /^[bcnops]/,\r\n peg$c31 = peg$classExpectation([\"b\", \"c\", \"n\", \"o\", \"p\", \"s\"], false, false),\r\n peg$c32 = \"*\",\r\n peg$c33 = peg$literalExpectation(\"*\", false),\r\n peg$c34 = function (w) {\r\n return w;\r\n },\r\n peg$c35 = /^[A-Z]/,\r\n peg$c36 = peg$classExpectation([\r\n [\"A\", \"Z\"]\r\n ], false, false),\r\n peg$c37 = /^[a-z]/,\r\n peg$c38 = peg$classExpectation([\r\n [\"a\", \"z\"]\r\n ], false, false),\r\n peg$c39 = function (e) {\r\n return e.join('');\r\n },\r\n peg$c40 = \"%\",\r\n peg$c41 = peg$literalExpectation(\"%\", false),\r\n peg$c42 = /^[1-9]/,\r\n peg$c43 = peg$classExpectation([\r\n [\"1\", \"9\"]\r\n ], false, false),\r\n peg$c44 = /^[0-9]/,\r\n peg$c45 = peg$classExpectation([\r\n [\"0\", \"9\"]\r\n ], false, false),\r\n peg$c46 = function (r) {\r\n if (r.length == 1) return Number(r);\r\n return Number(r.join('').replace('%', ''));\r\n },\r\n peg$c47 = \"@\",\r\n peg$c48 = peg$literalExpectation(\"@\", false),\r\n peg$c49 = \"TH\",\r\n peg$c50 = peg$literalExpectation(\"TH\", false),\r\n peg$c51 = /^[12]/,\r\n peg$c52 = peg$classExpectation([\"1\", \"2\"], false, false),\r\n peg$c53 = \"AL\",\r\n peg$c54 = peg$literalExpectation(\"AL\", false),\r\n peg$c55 = \"SP\",\r\n peg$c56 = peg$literalExpectation(\"SP\", false),\r\n peg$c57 = /^[1-3]/,\r\n peg$c58 = peg$classExpectation([\r\n [\"1\", \"3\"]\r\n ], false, false),\r\n peg$c59 = \"TB\",\r\n peg$c60 = peg$literalExpectation(\"TB\", false),\r\n peg$c61 = \"OH\",\r\n peg$c62 = peg$literalExpectation(\"OH\", false),\r\n peg$c63 = function (c) {\r\n if (!c[1]) return '@';\r\n if (c[1] == '@') return '@@';\r\n\r\n return c[1].join('').replace(',', '');\r\n },\r\n peg$c64 = function (c) {\r\n return c;\r\n },\r\n peg$c65 = \"+\",\r\n peg$c66 = peg$literalExpectation(\"+\", false),\r\n peg$c67 = function (c) {\r\n if (!c[1]) return 1;\r\n if (c[1] != '+') return Number(c[1].join(''));\r\n return 2;\r\n },\r\n peg$c68 = \"-\",\r\n peg$c69 = peg$literalExpectation(\"-\", false),\r\n peg$c70 = function (c) {\r\n if (!c[1]) return -1;\r\n if (c[1] != '-') return -Number(c[1].join(''));\r\n return -2;\r\n },\r\n peg$c71 = \"H\",\r\n peg$c72 = peg$literalExpectation(\"H\", false),\r\n peg$c73 = function (h) {\r\n if (h[1]) return Number(h[1]);\r\n return 1;\r\n },\r\n peg$c74 = \":\",\r\n peg$c75 = peg$literalExpectation(\":\", false),\r\n peg$c76 = /^[0]/,\r\n peg$c77 = peg$classExpectation([\"0\"], false, false),\r\n peg$c78 = function (c) {\r\n return Number(c[1][0] + c[1][1].join(''));\r\n },\r\n peg$c79 = function (i) {\r\n return Number(i.join(''));\r\n },\r\n\r\n peg$currPos = 0,\r\n peg$savedPos = 0,\r\n peg$posDetailsCache = [{\r\n line: 1,\r\n column: 1\r\n }],\r\n peg$maxFailPos = 0,\r\n peg$maxFailExpected = [],\r\n peg$silentFails = 0,\r\n\r\n peg$result;\r\n\r\n if (\"startRule\" in options) {\r\n if (!(options.startRule in peg$startRuleFunctions)) {\r\n throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");\r\n }\r\n\r\n peg$startRuleFunction = peg$startRuleFunctions[options.startRule];\r\n }\r\n\r\n function text() {\r\n return input.substring(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function location() {\r\n return peg$computeLocation(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function expected(description, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildStructuredError(\r\n [peg$otherExpectation(description)],\r\n input.substring(peg$savedPos, peg$currPos),\r\n location\r\n );\r\n }\r\n\r\n function error(message, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildSimpleError(message, location);\r\n }\r\n\r\n function peg$literalExpectation(text, ignoreCase) {\r\n return {\r\n type: \"literal\",\r\n text: text,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$classExpectation(parts, inverted, ignoreCase) {\r\n return {\r\n type: \"class\",\r\n parts: parts,\r\n inverted: inverted,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$anyExpectation() {\r\n return {\r\n type: \"any\"\r\n };\r\n }\r\n\r\n function peg$endExpectation() {\r\n return {\r\n type: \"end\"\r\n };\r\n }\r\n\r\n function peg$otherExpectation(description) {\r\n return {\r\n type: \"other\",\r\n description: description\r\n };\r\n }\r\n\r\n function peg$computePosDetails(pos) {\r\n var details = peg$posDetailsCache[pos],\r\n p;\r\n\r\n if (details) {\r\n return details;\r\n } else {\r\n p = pos - 1;\r\n while (!peg$posDetailsCache[p]) {\r\n p--;\r\n }\r\n\r\n details = peg$posDetailsCache[p];\r\n details = {\r\n line: details.line,\r\n column: details.column\r\n };\r\n\r\n while (p < pos) {\r\n if (input.charCodeAt(p) === 10) {\r\n details.line++;\r\n details.column = 1;\r\n } else {\r\n details.column++;\r\n }\r\n\r\n p++;\r\n }\r\n\r\n peg$posDetailsCache[pos] = details;\r\n return details;\r\n }\r\n }\r\n\r\n function peg$computeLocation(startPos, endPos) {\r\n var startPosDetails = peg$computePosDetails(startPos),\r\n endPosDetails = peg$computePosDetails(endPos);\r\n\r\n return {\r\n start: {\r\n offset: startPos,\r\n line: startPosDetails.line,\r\n column: startPosDetails.column\r\n },\r\n end: {\r\n offset: endPos,\r\n line: endPosDetails.line,\r\n column: endPosDetails.column\r\n }\r\n };\r\n }\r\n\r\n function peg$fail(expected) {\r\n if (peg$currPos < peg$maxFailPos) {\r\n return;\r\n }\r\n\r\n if (peg$currPos > peg$maxFailPos) {\r\n peg$maxFailPos = peg$currPos;\r\n peg$maxFailExpected = [];\r\n }\r\n\r\n peg$maxFailExpected.push(expected);\r\n }\r\n\r\n function peg$buildSimpleError(message, location) {\r\n return new peg$SyntaxError(message, null, null, location);\r\n }\r\n\r\n function peg$buildStructuredError(expected, found, location) {\r\n return new peg$SyntaxError(\r\n peg$SyntaxError.buildMessage(expected, found),\r\n expected,\r\n found,\r\n location\r\n );\r\n }\r\n\r\n function peg$parsechain() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n s2 = peg$parseatom();\r\n if (s2 !== peg$FAILED) {\r\n s3 = [];\r\n s4 = peg$parsebranch();\r\n while (s4 !== peg$FAILED) {\r\n s3.push(s4);\r\n s4 = peg$parsebranch();\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = [];\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n while (s5 !== peg$FAILED) {\r\n s4.push(s5);\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n s6 = peg$parsebranch();\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n s6 = peg$parsebranch();\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsechain();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = [];\r\n s9 = peg$parsebranch();\r\n while (s9 !== peg$FAILED) {\r\n s8.push(s9);\r\n s9 = peg$parsebranch();\r\n }\r\n if (s8 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c0(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebranch() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 40) {\r\n s2 = peg$c1;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c2);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parsebond();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = peg$parsechain();\r\n if (s4 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 41) {\r\n s5 = peg$c3;\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c4);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c5(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseatom() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseorganicsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsearomaticsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsebracketatom();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebond() {\r\n var s0, s1;\r\n s0 = peg$currPos;\r\n if (peg$c7.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n\r\n // Hack to resolve problem caused by:\r\n // O=C(N[C@@H](CC(O)=O)C(N[C@H](C1=CC=C(O)C=C1)C(N[C@@H](CC(O)=O)C(NCC(N[C@@H](C(N[C@@H]([C@H](C)CC(O)=O)C(N/C(C(O[C@H](C)[C@@H]2NC([C@H](CO)NC(C(O3)C3CCC)=O)=O)=O)=C\\\\\\\\C4=CNC5=C4C=CC=C5)=O)=O)[C@H](O)C(N)=O)=O)=O)=O)=O)[C@H](CC(O)=O)NC([C@@H](CC6=CNC7=C6C=CC=C7)NC2=O)=O\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n if (s1 === input.charAt(peg$currPos + 1)) {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n throw peg$buildSimpleError('The parser encountered a bond repetition.', peg$currPos + 1);\r\n }\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c8);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c9(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebracketatom() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 91) {\r\n s2 = peg$c10;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c11);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parseisotope();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c12) {\r\n s4 = peg$c12;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c13);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c14) {\r\n s4 = peg$c14;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c15);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsearomaticsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parseelementsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = peg$parsechiral();\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsehcount();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsecharge();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = peg$parseclass();\r\n if (s8 === peg$FAILED) {\r\n s8 = null;\r\n }\r\n if (s8 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 93) {\r\n s9 = peg$c16;\r\n peg$currPos++;\r\n } else {\r\n s9 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c17);\r\n }\r\n }\r\n if (s9 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8, s9];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c18(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseorganicsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 66) {\r\n s2 = peg$c19;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c20);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 114) {\r\n s3 = peg$c21;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c22);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 67) {\r\n s2 = peg$c23;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c24);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 108) {\r\n s3 = peg$c25;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c26);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c27.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c28);\r\n }\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c29(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsearomaticsymbol() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (peg$c30.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c31);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsewildcard() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 42) {\r\n s1 = peg$c32;\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c33);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c34(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseelementsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c35.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c36);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c37.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c38);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c39(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsering() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 37) {\r\n s2 = peg$c40;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c41);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c46(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsechiral() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s2 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s3 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c49) {\r\n s4 = peg$c49;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c50);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c53) {\r\n s4 = peg$c53;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c54);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c55) {\r\n s4 = peg$c55;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c56);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c57.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c58);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c59) {\r\n s4 = peg$c59;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c60);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c61) {\r\n s4 = peg$c61;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c62);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c63(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsecharge() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseposcharge();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsenegcharge();\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c64(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseposcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s2 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s3 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c67(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsenegcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s2 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s3 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c70(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsehcount() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 72) {\r\n s2 = peg$c71;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c72);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c73(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseclass() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 58) {\r\n s2 = peg$c74;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c75);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n if (peg$c76.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c77);\r\n }\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c78(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseisotope() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = null;\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c79(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n peg$result = peg$startRuleFunction();\r\n\r\n if (peg$result !== peg$FAILED && peg$currPos === input.length) {\r\n return peg$result;\r\n } else {\r\n if (peg$result !== peg$FAILED && peg$currPos < input.length) {\r\n peg$fail(peg$endExpectation());\r\n }\r\n\r\n throw peg$buildStructuredError(\r\n peg$maxFailExpected,\r\n peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,\r\n peg$maxFailPos < input.length ?\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) :\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n SyntaxError: peg$SyntaxError,\r\n parse: peg$parse\r\n };\r\n})();","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Vertex = require('./Vertex')\r\nconst RingConnection = require('./RingConnection')\r\n\r\n/** \r\n * A class representing a ring.\r\n * \r\n * @property {Number} id The id of this ring.\r\n * @property {Number[]} members An array containing the vertex ids of the ring members.\r\n * @property {Number[]} edges An array containing the edge ids of the edges between the ring members.\r\n * @property {Number[]} insiders An array containing the vertex ids of the vertices contained within the ring if it is a bridged ring.\r\n * @property {Number[]} neighbours An array containing the ids of neighbouring rings.\r\n * @property {Boolean} positioned A boolean indicating whether or not this ring has been positioned.\r\n * @property {Vector2} center The center of this ring.\r\n * @property {Ring[]} rings The rings contained within this ring if this ring is bridged.\r\n * @property {Boolean} isBridged A boolean whether or not this ring is bridged.\r\n * @property {Boolean} isPartOfBridged A boolean whether or not this ring is part of a bridge ring.\r\n * @property {Boolean} isSpiro A boolean whether or not this ring is part of a spiro.\r\n * @property {Boolean} isFused A boolean whether or not this ring is part of a fused ring.\r\n * @property {Number} centralAngle The central angle of this ring.\r\n * @property {Boolean} canFlip A boolean indicating whether or not this ring allows flipping of attached vertices to the inside of the ring.\r\n */\r\nclass Ring {\r\n /**\r\n * The constructor for the class Ring.\r\n *\r\n * @param {Number[]} members An array containing the vertex ids of the members of the ring to be created.\r\n */\r\n constructor(members) {\r\n this.id = null;\r\n this.members = members;\r\n this.edges = [];\r\n this.insiders = [];\r\n this.neighbours = [];\r\n this.positioned = false;\r\n this.center = new Vector2(0, 0);\r\n this.rings = [];\r\n this.isBridged = false;\r\n this.isPartOfBridged = false;\r\n this.isSpiro = false;\r\n this.isFused = false;\r\n this.centralAngle = 0.0;\r\n this.canFlip = true;\r\n }\r\n \r\n /**\r\n * Clones this ring and returns the clone.\r\n *\r\n * @returns {Ring} A clone of this ring.\r\n */\r\n clone() {\r\n let clone = new Ring(this.members);\r\n\r\n clone.id = this.id;\r\n clone.insiders = ArrayHelper.clone(this.insiders);\r\n clone.neighbours = ArrayHelper.clone(this.neighbours);\r\n clone.positioned = this.positioned;\r\n clone.center = this.center.clone();\r\n clone.rings = ArrayHelper.clone(this.rings);\r\n clone.isBridged = this.isBridged;\r\n clone.isPartOfBridged = this.isPartOfBridged;\r\n clone.isSpiro = this.isSpiro;\r\n clone.isFused = this.isFused;\r\n clone.centralAngle = this.centralAngle;\r\n clone.canFlip = this.canFlip;\r\n\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns the size (number of members) of this ring.\r\n *\r\n * @returns {Number} The size (number of members) of this ring.\r\n */\r\n getSize() {\r\n return this.members.length;\r\n }\r\n\r\n /**\r\n * Gets the polygon representation (an array of the ring-members positional vectors) of this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices representing the current molecule.\r\n * @returns {Vector2[]} An array of the positional vectors of the ring members.\r\n */\r\n getPolygon(vertices) {\r\n let polygon = [];\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n polygon.push(vertices[this.members[i]].position);\r\n }\r\n\r\n return polygon;\r\n }\r\n\r\n /**\r\n * Returns the angle of this ring in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n return Math.PI - this.centralAngle;\r\n }\r\n\r\n /**\r\n * Loops over the members of this ring from a given start position in a direction opposite to the vertex id passed as the previousId.\r\n *\r\n * @param {Vertex[]} vertices The vertices associated with the current molecule.\r\n * @param {Function} callback A callback with the current vertex id as a parameter.\r\n * @param {Number} startVertexId The vertex id of the start vertex.\r\n * @param {Number} previousVertexId The vertex id of the previous vertex (the loop calling the callback function will run in the opposite direction of this vertex).\r\n */\r\n eachMember(vertices, callback, startVertexId, previousVertexId) {\r\n startVertexId = startVertexId || startVertexId === 0 ? startVertexId : this.members[0];\r\n let current = startVertexId;\r\n let max = 0;\r\n\r\n while (current != null && max < 100) {\r\n let prev = current;\r\n \r\n callback(prev);\r\n current = vertices[current].getNextInRing(vertices, this.id, previousVertexId);\r\n previousVertexId = prev;\r\n \r\n // Stop while loop when arriving back at the start vertex\r\n if (current == startVertexId) {\r\n current = null;\r\n }\r\n\r\n max++;\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array containing the neighbouring rings of this ring ordered by ring size.\r\n *\r\n * @param {RingConnection[]} ringConnections An array of ring connections associated with the current molecule.\r\n * @returns {Object[]} An array of neighbouring rings sorted by ring size. Example: { n: 5, neighbour: 1 }.\r\n */\r\n getOrderedNeighbours(ringConnections) {\r\n let orderedNeighbours = Array(this.neighbours.length);\r\n \r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n let vertices = RingConnection.getVertices(ringConnections, this.id, this.neighbours[i]);\r\n \r\n orderedNeighbours[i] = {\r\n n: vertices.length,\r\n neighbour: this.neighbours[i]\r\n };\r\n }\r\n\r\n orderedNeighbours.sort(function (a, b) {\r\n // Sort highest to lowest\r\n return b.n - a.n;\r\n });\r\n\r\n return orderedNeighbours;\r\n }\r\n\r\n /**\r\n * Check whether this ring is an implicitly defined benzene-like (e.g. C1=CC=CC=C1) with 6 members and 3 double bonds.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring is an implicitly defined benzene-like.\r\n */\r\n isBenzeneLike(vertices) {\r\n let db = this.getDoubleBondCount(vertices);\r\n let length = this.members.length;\r\n\r\n return db === 3 && length === 6 ||\r\n db === 2 && length === 5 ;\r\n }\r\n\r\n /**\r\n * Get the number of double bonds inside this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Number} The number of double bonds inside this ring.\r\n */\r\n getDoubleBondCount(vertices) {\r\n let doubleBondCount = 0;\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n let atom = vertices[this.members[i]].value;\r\n\r\n if (atom.bondType === '=' || atom.branchBond === '=') {\r\n doubleBondCount++;\r\n }\r\n }\r\n\r\n return doubleBondCount;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring contains a member with a given vertex id.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not this ring contains a member with the given vertex id.\r\n */\r\n contains(vertexId) {\r\n for (let i = 0; i < this.members.length; i++) {\r\n if (this.members[i] == vertexId) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n\r\nmodule.exports = Ring;","//@ts-check\r\nconst Vertex = require('./Vertex')\r\nconst Ring = require('./Ring')\r\n\r\n/** \r\n * A class representing a ring connection.\r\n * \r\n * @property {Number} id The id of this ring connection.\r\n * @property {Number} firstRingId A ring id.\r\n * @property {Number} secondRingId A ring id.\r\n * @property {Set} vertices A set containing the vertex ids participating in the ring connection.\r\n */\r\nclass RingConnection {\r\n /**\r\n * The constructor for the class RingConnection.\r\n *\r\n * @param {Ring} firstRing A ring.\r\n * @param {Ring} secondRing A ring.\r\n */\r\n constructor(firstRing, secondRing) {\r\n this.id = null;\r\n this.firstRingId = firstRing.id;\r\n this.secondRingId = secondRing.id;\r\n this.vertices = new Set();\r\n\r\n for (var m = 0; m < firstRing.members.length; m++) {\r\n let c = firstRing.members[m];\r\n\r\n for (let n = 0; n < secondRing.members.length; n++) {\r\n let d = secondRing.members[n];\r\n\r\n if (c === d) {\r\n this.addVertex(c);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adding a vertex to the ring connection.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n */\r\n addVertex(vertexId) {\r\n this.vertices.add(vertexId);\r\n }\r\n\r\n /**\r\n * Update the ring id of this ring connection that is not the ring id supplied as the second argument.\r\n *\r\n * @param {Number} ringId A ring id. The new ring id to be set.\r\n * @param {Number} otherRingId A ring id. The id that is NOT to be updated.\r\n */\r\n updateOther(ringId, otherRingId) {\r\n if (this.firstRingId === otherRingId) {\r\n this.secondRingId = ringId;\r\n } else {\r\n this.firstRingId = ringId;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.\r\n * \r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.\r\n */\r\n containsRing(ringId) {\r\n return this.firstRingId === ringId || this.secondRingId === ringId;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring connection is a bridge in a bridged ring.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.\r\n */\r\n isBridge(vertices) {\r\n if (this.vertices.size > 2) {\r\n return true;\r\n }\r\n\r\n for (let vertexId of this.vertices) {\r\n if(vertices[vertexId].value.rings.length > 2) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two rings are connected by a bridged bond.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.\r\n */\r\n static isBridge(ringConnections, vertices, firstRingId, secondRingId) {\r\n let ringConnection = null;\r\n \r\n for (let i = 0; i < ringConnections.length; i++) {\r\n ringConnection = ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return ringConnection.isBridge(vertices);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Retruns the neighbouring rings of a given ring.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array of ring ids of neighbouring rings.\r\n */\r\n static getNeighbours(ringConnections, ringId) {\r\n let neighbours = [];\r\n\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n \r\n if (ringConnection.firstRingId === ringId) {\r\n neighbours.push(ringConnection.secondRingId);\r\n } else if (ringConnection.secondRingId === ringId) {\r\n neighbours.push(ringConnection.firstRingId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Returns an array of vertex ids associated with a given ring connection.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Number[]} An array of vertex ids associated with the ring connection.\r\n */\r\n static getVertices(ringConnections, firstRingId, secondRingId) {\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return [...ringConnection.vertices];\r\n }\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = RingConnection","//@ts-check\r\nconst Graph = require('./Graph')\r\n\r\n/** A class encapsulating the functionality to find the smallest set of smallest rings in a graph. */\r\nclass SSSR {\r\n /**\r\n * Returns an array containing arrays, each representing a ring from the smallest set of smallest rings in the graph.\r\n * \r\n * @param {Graph} graph A Graph object.\r\n * @param {Boolean} [experimental=false] Whether or not to use experimental SSSR.\r\n * @returns {Array[]} An array containing arrays, each representing a ring from the smallest set of smallest rings in the group.\r\n */\r\n static getRings(graph, experimental=false) {\r\n let adjacencyMatrix = graph.getComponentsAdjacencyMatrix();\r\n if (adjacencyMatrix.length === 0) {\r\n return null;\r\n }\r\n\r\n let connectedComponents = Graph.getConnectedComponents(adjacencyMatrix);\r\n let rings = Array();\r\n\r\n for (var i = 0; i < connectedComponents.length; i++) {\r\n let connectedComponent = connectedComponents[i];\r\n let ccAdjacencyMatrix = graph.getSubgraphAdjacencyMatrix([...connectedComponent]);\r\n\r\n let arrBondCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n let arrRingCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n arrRingCount[j] = 0;\r\n arrBondCount[j] = 0;\r\n\r\n for (var k = 0; k < ccAdjacencyMatrix[j].length; k++) {\r\n arrBondCount[j] += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n // Get the edge number and the theoretical number of rings in SSSR\r\n let nEdges = 0;\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n for (var k = j + 1; k < ccAdjacencyMatrix.length; k++) {\r\n nEdges += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n let nSssr = nEdges - ccAdjacencyMatrix.length + 1;\r\n\r\n // console.log(nEdges, ccAdjacencyMatrix.length, nSssr);\r\n // console.log(SSSR.getEdgeList(ccAdjacencyMatrix));\r\n // console.log(ccAdjacencyMatrix);\r\n\r\n // If all vertices have 3 incident edges, calculate with different formula (see Euler)\r\n let allThree = true;\r\n for (var j = 0; j < arrBondCount.length; j++) {\r\n if (arrBondCount[j] !== 3) {\r\n allThree = false;\r\n }\r\n }\r\n\r\n if (allThree) {\r\n nSssr = 2.0 + nEdges - ccAdjacencyMatrix.length;\r\n }\r\n\r\n // All vertices are part of one ring if theres only one ring.\r\n if (nSssr === 1) {\r\n rings.push([...connectedComponent]);\r\n continue;\r\n }\r\n \r\n if (experimental) {\r\n nSssr = 999;\r\n }\r\n\r\n let { d, pe, pe_prime } = SSSR.getPathIncludedDistanceMatrices(ccAdjacencyMatrix);\r\n let c = SSSR.getRingCandidates(d, pe, pe_prime);\r\n let sssr = SSSR.getSSSR(c, d, ccAdjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nSssr);\r\n\r\n for (var j = 0; j < sssr.length; j++) {\r\n let ring = Array(sssr[j].size);\r\n let index = 0;\r\n\r\n for (let val of sssr[j]) {\r\n // Get the original id of the vertex back\r\n ring[index++] = connectedComponent[val];\r\n }\r\n\r\n rings.push(ring);\r\n }\r\n }\r\n \r\n\r\n // So, for some reason, this would return three rings for C1CCCC2CC1CCCC2, which is wrong\r\n // As I don't have time to fix this properly, it will stay in. I'm sorry next person who works\r\n // on it. At that point it might be best to reimplement the whole SSSR thing...\r\n return rings;\r\n }\r\n\r\n /**\r\n * Creates a printable string from a matrix (2D array).\r\n * \r\n * @param {Array[]} matrix A 2D array.\r\n * @returns {String} A string representing the matrix.\r\n */\r\n static matrixToString(matrix) {\r\n let str = '';\r\n\r\n for (var i = 0; i < matrix.length; i++) {\r\n for (var j = 0; j < matrix[i].length; j++) {\r\n str += matrix[i][j] + ' ';\r\n }\r\n\r\n str += '\\n';\r\n }\r\n\r\n return str;\r\n }\r\n\r\n /**\r\n * Returnes the two path-included distance matrices used to find the sssr.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Object} The path-included distance matrices. { p1, p2 }\r\n */\r\n static getPathIncludedDistanceMatrices(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let d = Array(length);\r\n let pe = Array(length);\r\n let pe_prime = Array(length);\r\n var l = 0;\r\n var m = 0;\r\n var n = 0;\r\n\r\n var i = length;\r\n while (i--) {\r\n d[i] = Array(length);\r\n pe[i] = Array(length);\r\n pe_prime[i] = Array(length);\r\n\r\n var j = length;\r\n while (j--) {\r\n d[i][j] = (i === j || adjacencyMatrix[i][j] === 1) ? adjacencyMatrix[i][j] : Number.POSITIVE_INFINITY;\r\n\r\n if (d[i][j] === 1) {\r\n pe[i][j] = [[[i, j]]];\r\n } else {\r\n pe[i][j] = Array();\r\n }\r\n\r\n pe_prime[i][j] = Array();\r\n }\r\n }\r\n\r\n var k = length;\r\n var j;\r\n while (k--) {\r\n i = length;\r\n while (i--) {\r\n j = length;\r\n while (j--) {\r\n const previousPathLength = d[i][j];\r\n const newPathLength = d[i][k] + d[k][j];\r\n\r\n if (previousPathLength > newPathLength) {\r\n var l, m, n;\r\n if (previousPathLength === newPathLength + 1) {\r\n pe_prime[i][j] = [pe[i][j].length];\r\n l = pe[i][j].length\r\n while (l--) {\r\n pe_prime[i][j][l] = [pe[i][j][l].length];\r\n m = pe[i][j][l].length\r\n while (m--) {\r\n pe_prime[i][j][l][m] = [pe[i][j][l][m].length];\r\n n = pe[i][j][l][m].length;\r\n while (n--) {\r\n pe_prime[i][j][l][m][n] = [pe[i][j][l][m][0], pe[i][j][l][m][1]];\r\n }\r\n }\r\n }\r\n } else {\r\n pe_prime[i][j] = Array();\r\n }\r\n\r\n d[i][j] = newPathLength;\r\n\r\n pe[i][j] = [[]];\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[k][j][0][l]);\r\n }\r\n } else if (previousPathLength === newPathLength) {\r\n if (pe[i][k].length && pe[k][j].length) {\r\n var l;\r\n if (pe[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j][0] = tmp\r\n }\r\n }\r\n } else if (previousPathLength === newPathLength - 1) {\r\n var l;\r\n if (pe_prime[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j][0] = tmp;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n d: d,\r\n pe: pe,\r\n pe_prime: pe_prime\r\n };\r\n }\r\n\r\n /**\r\n * Get the ring candidates from the path-included distance matrices.\r\n * \r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @returns {Array[]} The ring candidates.\r\n */\r\n static getRingCandidates(d, pe, pe_prime) {\r\n let length = d.length;\r\n let candidates = Array();\r\n let c = 0;\r\n\r\n for (let i = 0; i < length; i++) {\r\n for (let j = 0; j < length; j++) {\r\n if (d[i][j] === 0 || (pe[i][j].length === 1 && pe_prime[i][j] === 0)) {\r\n continue;\r\n } else {\r\n // c is the number of vertices in the cycle.\r\n if (pe_prime[i][j].length !== 0) {\r\n c = 2 * (d[i][j] + 0.5);\r\n } else {\r\n c = 2 * d[i][j];\r\n }\r\n\r\n if (c !== Infinity) {\r\n candidates.push([c, pe[i][j], pe_prime[i][j]]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Candidates have to be sorted by c\r\n candidates.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n\r\n return candidates;\r\n }\r\n\r\n /**\r\n * Searches the candidates for the smallest set of smallest rings.\r\n * \r\n * @param {Array[]} c The candidates.\r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @param {Number} nsssr The theoretical number of rings in the graph.\r\n * @returns {Set[]} The smallest set of smallest rings.\r\n */\r\n static getSSSR(c, d, adjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nsssr) {\r\n let cSssr = Array();\r\n let allBonds = Array();\r\n\r\n for (let i = 0; i < c.length; i++) {\r\n if (c[i][0] % 2 !== 0) {\r\n for (let j = 0; j < c[i][2].length; j++) {\r\n let bonds = c[i][1][0].concat(c[i][2][j]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n } else {\r\n for (let j = 0; j < c[i][1].length - 1; j++) {\r\n let bonds = c[i][1][j].concat(c[i][1][j + 1]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return cSssr;\r\n }\r\n\r\n /**\r\n * Returns the number of edges in a graph defined by an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of edges in the graph defined by the adjacency matrix.\r\n */\r\n static getEdgeCount(adjacencyMatrix) {\r\n let edgeCount = 0;\r\n let length = adjacencyMatrix.length;\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeCount++;\r\n }\r\n }\r\n }\r\n\r\n return edgeCount;\r\n }\r\n\r\n /**\r\n * Returns an edge list constructed form an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Array[]} An edge list. E.g. [ [ 0, 1 ], ..., [ 16, 2 ] ]\r\n */\r\n static getEdgeList(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let edgeList = Array();\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeList.push([i, j]);\r\n }\r\n }\r\n }\r\n\r\n return edgeList;\r\n }\r\n\r\n /**\r\n * Return a set of vertex indices contained in an array of bonds.\r\n * \r\n * @param {Array} bonds An array of bonds. A bond is defined as [ sourceVertexId, targetVertexId ].\r\n * @returns {Set} An array of vertices.\r\n */\r\n static bondsToAtoms(bonds) {\r\n let atoms = new Set();\r\n\r\n var i = bonds.length;\r\n while (i--) {\r\n atoms.add(bonds[i][0]);\r\n atoms.add(bonds[i][1]);\r\n }\r\n return atoms;\r\n }\r\n\r\n /**\r\n * Returns the number of bonds within a set of atoms.\r\n * \r\n * @param {Set} atoms An array of atom ids.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of bonds in a set of atoms.\r\n */\r\n static getBondCount(atoms, adjacencyMatrix) {\r\n let count = 0;\r\n for (let u of atoms) {\r\n for (let v of atoms) {\r\n if (u === v) {\r\n continue;\r\n }\r\n count += adjacencyMatrix[u][v]\r\n }\r\n }\r\n\r\n return count / 2;\r\n }\r\n\r\n /**\r\n * Checks whether or not a given path already exists in an array of paths.\r\n * \r\n * @param {Set[]} pathSets An array of sets each representing a path.\r\n * @param {Set} pathSet A set representing a path.\r\n * @param {Array[]} bonds The bonds associated with the current path.\r\n * @param {Array[]} allBonds All bonds currently associated with rings in the SSSR set.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @returns {Boolean} A boolean indicating whether or not a give path is contained within a set.\r\n */\r\n static pathSetsContain(pathSets, pathSet, bonds, allBonds, arrBondCount, arrRingCount) {\r\n var i = pathSets.length;\r\n while (i--) {\r\n if (SSSR.isSupersetOf(pathSet, pathSets[i])) {\r\n return true;\r\n }\r\n\r\n if (pathSets[i].size !== pathSet.size) {\r\n continue;\r\n }\r\n\r\n if (SSSR.areSetsEqual(pathSets[i], pathSet)) {\r\n return true;\r\n }\r\n }\r\n\r\n // Check if the edges from the candidate are already all contained within the paths of the set of paths.\r\n // TODO: For some reason, this does not replace the isSupersetOf method above -> why?\r\n let count = 0;\r\n let allContained = false;\r\n i = bonds.length;\r\n while (i--) {\r\n var j = allBonds.length;\r\n while (j--) {\r\n if (bonds[i][0] === allBonds[j][0] && bonds[i][1] === allBonds[j][1] ||\r\n bonds[i][1] === allBonds[j][0] && bonds[i][0] === allBonds[j][1]) {\r\n count++;\r\n }\r\n\r\n if (count === bonds.length) {\r\n allContained = true;\r\n }\r\n }\r\n }\r\n\r\n // If all the bonds and thus vertices are already contained within other rings\r\n // check if there's one vertex with ringCount < bondCount\r\n let specialCase = false;\r\n if (allContained) {\r\n for (let element of pathSet) {\r\n if (arrRingCount[element] < arrBondCount[element]) {\r\n specialCase = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (allContained && !specialCase) {\r\n return true;\r\n }\r\n\r\n // Update the ring counts for the vertices\r\n for (let element of pathSet) {\r\n arrRingCount[element]++;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two sets are equal (contain the same elements).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not the two sets are equal.\r\n */\r\n static areSetsEqual(setA, setB) {\r\n if (setA.size !== setB.size) {\r\n return false;\r\n }\r\n\r\n for (let element of setA) {\r\n if (!setB.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Checks whether or not a set (setA) is a superset of another set (setB).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not setB is a superset of setA.\r\n */\r\n static isSupersetOf(setA, setB) {\r\n for (var element of setB) {\r\n if (!setA.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\nmodule.exports = SSSR;","//@ts-check\r\n\r\nclass SequenceType {\r\n\r\n static get VALUES() {\r\n return {\r\n LINEAR: \"linear\",\r\n CYCLIC: \"cyclic\",\r\n BRANCH: \"branched\",\r\n BRANCH_CYCLIC: \"branch-cyclic\",\r\n LINEAR_POLYKETIDE: \"linear-polyketide\",\r\n CYCLIC_POLYKETIDE: \"cyclic-polyketide\",\r\n OTHER: \"other\",\r\n }\r\n }\r\n\r\n static getTypeFromValues(isCyclic, isBranch, isOther) {\r\n if (isOther) { return this.VALUES.OTHER;}\r\n if (!isCyclic && !isBranch) {\r\n return this.VALUES.LINEAR;\r\n } else if(isCyclic && !isBranch) {\r\n return this.VALUES.CYCLIC;\r\n } else if (!isCyclic) {\r\n return this.VALUES.BRANCH;\r\n } else {\r\n return this.VALUES.BRANCH_CYCLIC;\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = SequenceType;\r\n","//@ts-check\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst VertexState = require('./VertexState');\r\nconst Neighbour = require('./Neighbour');\r\nconst Direction = require('./Direction');\r\n\r\nclass SmallGraph {\r\n\r\n constructor() {\r\n this._nodes = [];\r\n this.isOther = false;\r\n this._branch = false;\r\n this.isCyclic = false;\r\n this.isBranched = false;\r\n this.sequenceType = SequenceType.VALUES.LINEAR;\r\n this._nodeOnRing = null;\r\n }\r\n\r\n addVertex(node) {\r\n this._nodes.push(node);\r\n }\r\n\r\n addNeighbour(nodeId, neighbour, direction) {\r\n this._nodes[nodeId].addNeighbour(new Neighbour(neighbour, direction));\r\n }\r\n\r\n dfsInitialization() {\r\n this._nodes.forEach(e => e.vertexState = VertexState.VALUES.NOT_FOUND);\r\n }\r\n\r\n getSourceNode() {\r\n let ends = [];\r\n for (let index = 0; index < this._nodes.length; ++index) {\r\n if (this._nodes[index].neighbours.length === 1) {\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.C) {\r\n return this._nodes[index];\r\n }\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.POLYKETIDE) {\r\n return this._nodes[index];\r\n }\r\n ends.push(this._nodes[index]);\r\n }\r\n }\r\n if (ends.length > 0) {\r\n return ends[0];\r\n }\r\n return null;\r\n }\r\n\r\n oneCyclic() {\r\n if (this._nodes.length === 0) {\r\n return false;\r\n }\r\n this.dfsInitialization();\r\n this.isCyclic = false;\r\n this.dfsCyclic(this._nodes[0], -1);\r\n }\r\n\r\n dfsCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = vertex;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.neighbours.length; ++i) {\r\n if (vertexFromId !== vertex.neighbours[i].neighbour) {\r\n this.dfsCyclic(this._nodes[vertex.neighbours[i].neighbour], vertex.id);\r\n }\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSequenceStart() {\r\n if (this._nodes.length === 0) {\r\n return;\r\n }\r\n this.dfsInitialization();\r\n this.sequence = \"\";\r\n if (this.isCyclic) {\r\n this.findRing(this._nodeOnRing);\r\n this.dfsSequenceCyclic(this._nodeOnRing);\r\n } else {\r\n let sourceNode = this.getSourceNode();\r\n if (sourceNode !== null) {\r\n this.dfsSequence(this.getSourceNode(), -1);\r\n } else {\r\n this.sequenceType = 'other';\r\n this.isOther = true;\r\n return;\r\n }\r\n }\r\n if (this.sequence.charAt(this.sequence.length - 1) === '-') {\r\n this.sequence = this.sequence.substr(0, this.sequence.length - 1);\r\n }\r\n this.sequenceType = SequenceType.getTypeFromValues(this.isCyclic, this.isBranched, this.isOther);\r\n }\r\n\r\n arrayContainsTimes(array, searchValue, times) {\r\n let cnt = 0;\r\n for (let index = 0; index < array.length; ++index) {\r\n if (array[index].neighbour === searchValue) {\r\n cnt++;\r\n if (cnt === times) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n findRing(start) {\r\n let queue = [];\r\n let firstPath = [start.id];\r\n let firstPass = true;\r\n queue.push(firstPath);\r\n while (queue.length !== 0) {\r\n let path = queue.pop();\r\n let last = path[path.length - 1];\r\n let node = this._nodes[last];\r\n if (node.id === start.id && !firstPass) {\r\n if (path.length === 3 && path[0] === path[2] && !this.arrayContainsTimes(this._nodes[path[0]].neighbours, path[1], 2)) {\r\n continue;\r\n }\r\n path.forEach(v => this._nodes[v].onRing = true);\r\n continue;\r\n }\r\n node.neighbours.forEach(\r\n neighbour => {\r\n if (!path.some(e => e === neighbour.neighbour) || neighbour.neighbour === start.id) {\r\n let newPath = [...path];\r\n newPath.push(neighbour.neighbour);\r\n queue.push(newPath);\r\n }\r\n }\r\n );\r\n firstPass = false;\r\n }\r\n }\r\n\r\n sortByRingPreference(array) {\r\n let sortedArray = [...array];\r\n sortedArray.sort((a, b) => {\r\n if (this._nodes[a.neighbour].onRing === this._nodes[b.neighbour].onRing) {\r\n if (a.direction > b.direction) {\r\n return -1;\r\n } else if (a.direction < b.direction) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n } else if (this._nodes[a.neighbour].onRing) {\r\n return 1;\r\n } else {\r\n return -1;\r\n }\r\n });\r\n return sortedArray;\r\n }\r\n\r\n dfsSequenceCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n let sortedNeighbours = this.sortByRingPreference(vertex.neighbours);\r\n for (let index = 0; index < sortedNeighbours.length; ++index) {\r\n if (vertexFromId === sortedNeighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequenceCyclic(this._nodes[sortedNeighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n printVertex(vertexId) {\r\n this.sequence += `[${vertexId}]`;\r\n }\r\n\r\n printDash() {\r\n if (']' === this.sequence[this.sequence.length - 1]) {\r\n this.sequence += '-';\r\n }\r\n }\r\n\r\n printLeftBrace(vertex) {\r\n if (vertex.neighbours.length > 2) {\r\n if (this.isBranched) {\r\n this.isOther = true;\r\n }\r\n this.sequence += '\\\\(';\r\n this._branch = true;\r\n this.isBranched = true;\r\n }\r\n }\r\n\r\n printRightBrace() {\r\n if (this._branch) {\r\n this.sequence += '\\\\)';\r\n this._branch = false;\r\n }\r\n }\r\n\r\n dfsSequence(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n for (let index = 0; index < vertex.neighbours.length; ++index) {\r\n if (vertexFromId === vertex.neighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequence(this._nodes[vertex.neighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n}\r\n\r\nmodule.exports = SmallGraph;\r\n","// we use the drawer to do all the preprocessing. then we take over the drawing\r\n// portion to output to svg\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Atom = require('./Atom');\r\nconst Drawer = require('./Drawer');\r\nconst Graph = require('./Graph');\r\nconst Line = require('./Line');\r\nconst SvgWrapper = require('./SvgWrapper');\r\nconst ThemeManager = require('./ThemeManager');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgDrawer {\r\n constructor(options) {\r\n this.preprocessor = new Drawer(options);\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to an svg element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML svg element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n\r\n * @returns {Oject} The dimensions of the drawing in { width, height }\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n let preprocessor = this.preprocessor;\r\n\r\n preprocessor.initDraw(data, themeName, infoOnly);\r\n\r\n if (!infoOnly) {\r\n this.themeManager = new ThemeManager(this.preprocessor.opts.themes, themeName);\r\n this.svgWrapper = new SvgWrapper(this.themeManager, target, this.preprocessor.opts);\r\n }\r\n\r\n preprocessor.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.svgWrapper.determineDimensions(preprocessor.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(preprocessor.opts.debug);\r\n this.drawVertices(preprocessor.opts.debug);\r\n\r\n if (preprocessor.opts.debug) {\r\n console.log(preprocessor.graph);\r\n console.log(preprocessor.rings);\r\n console.log(preprocessor.ringConnections);\r\n }\r\n\r\n return this.svgWrapper.constructSvg();\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let preprocessor = this.preprocessor,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n drawn = Array(this.preprocessor.graph.edges.length);\r\n\r\n drawn.fill(false);\r\n\r\n graph.traverseBF(0, vertex => {\r\n let edges = graph.getEdges(vertex.id);\r\n for (var i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n this.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let ring = rings[i];\r\n\r\n if (preprocessor.isRingAromatic(ring)) {\r\n this.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bond.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n svgWrapper = this.svgWrapper,\r\n edge = preprocessor.graph.edges[edgeId],\r\n vertexA = preprocessor.graph.vertices[edge.sourceId],\r\n vertexB = preprocessor.graph.vertices[edge.targetId],\r\n elementA = vertexA.value.element,\r\n elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && preprocessor.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position,\r\n b = vertexB.position,\r\n normals = preprocessor.getEdgeNormals(edge),\r\n // Create a point on each side of the line\r\n sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || preprocessor.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && preprocessor.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = preprocessor.areVerticesInSameRing(vertexA, vertexB);\r\n let s = preprocessor.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(opts.bondSpacing);\r\n normals[1].multiplyScalar(opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line = null;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n }\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n // preprocessor.canvasWrapper.drawLine(line, true);\r\n svgWrapper.drawLine(line, true);\r\n } else {\r\n // preprocessor.canvasWrapper.drawLine(line);\r\n svgWrapper.drawLine(line);\r\n }\r\n\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((edge.center || vertexA.isTerminal() && vertexB.isTerminal()) ||\r\n (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1)) {\r\n this.multiplyNormals(normals, opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB),\r\n lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n } else if ((s.sideCount[0] > s.sideCount[1]) ||\r\n (s.totalSideCount[0] > s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((s.sideCount[0] < s.sideCount[1]) ||\r\n (s.totalSideCount[0] <= s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n svgWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else if (edge.wedge === 'down') {\r\n svgWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else {\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n svgWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n svgWrapper = this.svgWrapper;\r\n\r\n var i = graph.vertices.length;\r\n for (var i = 0; i < graph.vertices.length; i++) {\r\n let vertex = graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(graph.vertices);\r\n let isTerminal = opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (opts.atomVisualization === 'allballs') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || graph.vertices.length === 1) {\r\n if (opts.atomVisualization === 'default') {\r\n svgWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (opts.atomVisualization === 'balls') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = graph.vertices[vertex.neighbours[0]].position;\r\n let b = graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n svgWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (opts.debug) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let center = rings[i].center;\r\n svgWrapper.drawDebugPoint(center.x, center.y, 'r: ' + rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.preprocessor.getTotalOverlapScore();\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n return this.preprocessor.getMolecularFormula();\r\n }\r\n\r\n /**\r\n * @param {Array} normals list of normals to multiply\r\n * @param {Number} spacing value to multiply normals by\r\n */\r\n multiplyNormals(normals, spacing) {\r\n normals[0].multiplyScalar(spacing);\r\n normals[1].multiplyScalar(spacing);\r\n }\r\n}\r\n\r\nmodule.exports = SvgDrawer;","const {\r\n getChargeText\r\n} = require('./UtilityFunctions');\r\n\r\nconst Line = require('./Line');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgWrapper {\r\n constructor(themeManager, target, options) {\r\n this.svg = document.getElementById(target);\r\n this.opts = options;\r\n this.gradientId = 0;\r\n\r\n // maintain a list of line elements and their corresponding gradients\r\n // maintain a list of vertex elements\r\n this.paths = [];\r\n this.vertices = [];\r\n this.gradients = [];\r\n\r\n // maintain the offset for drawing purposes\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n // maintain the dimensions\r\n this.drawingWidth = 0;\r\n this.drawingHeight = 0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // for managing color schemes\r\n this.themeManager = themeManager;\r\n\r\n // create the mask\r\n this.maskElements = [];\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\r\n mask.setAttributeNS(null, 'x', 0);\r\n mask.setAttributeNS(null, 'y', 0);\r\n mask.setAttributeNS(null, 'width', '100%');\r\n mask.setAttributeNS(null, 'height', '100%');\r\n mask.setAttributeNS(null, 'fill', 'white');\r\n\r\n this.maskElements.push(mask);\r\n\r\n // clear the svg element\r\n while (this.svg.firstChild) {\r\n this.svg.removeChild(this.svg.firstChild);\r\n }\r\n }\r\n\r\n constructSvg() {\r\n // TODO: add the defs element to put gradients in\r\n let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'),\r\n masks = document.createElementNS('http://www.w3.org/2000/svg', 'mask'),\r\n style = document.createElementNS('http://www.w3.org/2000/svg', 'style'),\r\n paths = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n vertices = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n pathChildNodes = this.paths;\r\n\r\n // give the mask an id\r\n masks.setAttributeNS(null, 'id', 'text-mask');\r\n\r\n // create the css styles\r\n style.appendChild(document.createTextNode(`\r\n .element {\r\n font: ${this.opts.fontSizeLarge}pt Helvetica, Arial, sans-serif;\r\n alignment-baseline: 'middle';\r\n }\r\n .sub {\r\n font: ${this.opts.fontSizeSmall}pt Helvetica, Arial, sans-serif;\r\n }\r\n `));\r\n\r\n for (let path of pathChildNodes) {\r\n paths.appendChild(path);\r\n }\r\n for (let vertex of this.vertices) {\r\n vertices.appendChild(vertex);\r\n }\r\n for (let mask of this.maskElements) {\r\n masks.appendChild(mask);\r\n }\r\n for (let gradient of this.gradients) {\r\n defs.appendChild(gradient);\r\n }\r\n\r\n paths.setAttributeNS(null, 'mask', 'url(#text-mask)');\r\n\r\n if (this.svg) {\r\n this.svg.appendChild(defs);\r\n this.svg.appendChild(masks);\r\n this.svg.appendChild(style);\r\n this.svg.appendChild(paths);\r\n this.svg.appendChild(vertices);\r\n return this.svg;\r\n } else {\r\n let container = document.createElementNS('http://www.w3.org/2000/svg', 'g');\r\n container.appendChild(defs);\r\n container.appendChild(masks);\r\n container.appendChild(style);\r\n container.appendChild(paths);\r\n container.appendChild(vertices);\r\n return container;\r\n }\r\n }\r\n\r\n /**\r\n * Create a linear gradient to apply to a line\r\n *\r\n * @param {Line} line the line to apply the gradiation to.\r\n */\r\n createGradient(line) {\r\n // create the gradient and add it\r\n let gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient'),\r\n gradientUrl = `line-${this.gradientId++}`,\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n gradient.setAttributeNS(null, 'id', gradientUrl);\r\n gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\r\n gradient.setAttributeNS(null, 'x1', fromX);\r\n gradient.setAttributeNS(null, 'y1', fromY);\r\n gradient.setAttributeNS(null, 'x2', toX);\r\n gradient.setAttributeNS(null, 'y2', toY);\r\n\r\n let firstStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n firstStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getLeftElement()) || this.themeManager.getColor('C'));\r\n firstStop.setAttributeNS(null, 'offset', '20%');\r\n\r\n let secondStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n secondStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getRightElement() || this.themeManager.getColor('C')));\r\n secondStop.setAttributeNS(null, 'offset', '100%');\r\n\r\n gradient.appendChild(firstStop);\r\n gradient.appendChild(secondStop);\r\n\r\n this.gradients.push(gradient);\r\n\r\n return gradientUrl;\r\n }\r\n\r\n /**\r\n * Create a tspan element for sub or super scripts that styles the text\r\n * appropriately as one of those text types.\r\n *\r\n * @param {String} text the actual text\r\n * @param {String} shift the type of text, either 'sub', or 'super'\r\n */\r\n createSubSuperScripts(text, shift) {\r\n let elem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n elem.setAttributeNS(null, 'baseline-shift', shift);\r\n elem.appendChild(document.createTextNode(text));\r\n elem.setAttributeNS(null, 'class', 'sub');\r\n\r\n return elem;\r\n }\r\n\r\n /**\r\n * Determine drawing dimensiosn based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n determineDimensions(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n let padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n let scaleX = this.svg.clientWidth / this.drawingWidth;\r\n let scaleY = this.svg.clientHeight / this.drawingHeight;\r\n\r\n let scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n let viewBoxDim = Math.round(this.drawingWidth > this.drawingHeight ? this.drawingWidth : this.drawingHeight);\r\n\r\n this.svg.setAttributeNS(null, 'viewBox', `0 0 ${viewBoxDim} ${viewBoxDim}`);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.svg.clientHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.svg.clientWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Draw an svg ellipse as a ball.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n ball.setAttributeNS(null, 'cx', x + this.offsetX);\r\n ball.setAttributeNS(null, 'cy', y + this.offsetY);\r\n ball.setAttributeNS(null, 'r', this.opts.bondLength / 4.5);\r\n ball.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n\r\n this.vertices.push(ball);\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone(),\r\n normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral(),\r\n start,\r\n end;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n } else {\r\n start = l;\r\n end = r;\r\n }\r\n\r\n let dir = Vector2.subtract(end, start).normalize(),\r\n length = line.getLength(),\r\n step = 1.25 / (length / (this.opts.bondThickness * 3.0)),\r\n changed = false;\r\n\r\n let gradient = this.createGradient(line);\r\n\r\n for (let t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length),\r\n startDash = Vector2.add(start, to),\r\n width = 1.5 * t,\r\n dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n startDash.subtract(dashOffset);\r\n let endDash = startDash.clone();\r\n endDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n\r\n this.drawLine(new Line(startDash, endDash), null, gradient);\r\n }\r\n }\r\n\r\n /**\r\n * Draws a debug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + this.offsetX);\r\n point.setAttributeNS(null, 'cy', y + this.offsetY);\r\n point.setAttributeNS(null, 'r', '2');\r\n point.setAttributeNS(null, 'fill', '#f00');\r\n this.vertices.push(point);\r\n this.drawDebugText(x, y, debugText);\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\r\n textElem.setAttributeNS(null, 'x', x + this.offsetX);\r\n textElem.setAttributeNS(null, 'y', y + this.offsetY);\r\n textElem.setAttributeNS(null, 'class', 'debug');\r\n textElem.setAttributeNS(null, 'fill', '#ff0000');\r\n textElem.setAttributeNS(null, 'style', `\r\n font: 5px Droid Sans, sans-serif;\r\n `);\r\n textElem.appendChild(document.createTextNode(text));\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * Draws a line.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} dashed defaults to false.\r\n * @param {String} gradient gradient url. Defaults to null.\r\n */\r\n drawLine(line, dashed = false, gradient = null) {\r\n let opts = this.opts,\r\n stylesArr = [\r\n ['stroke-linecap', 'round'],\r\n ['stroke-dasharray', dashed ? '5, 5' : 'none'],\r\n ],\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n let styles = stylesArr.map(sub => sub.join(':')).join(';'),\r\n lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line');\r\n\r\n lineElem.setAttributeNS(null, 'x1', fromX);\r\n lineElem.setAttributeNS(null, 'y1', fromY);\r\n lineElem.setAttributeNS(null, 'x2', toX);\r\n lineElem.setAttributeNS(null, 'y2', toY);\r\n lineElem.setAttributeNS(null, 'style', styles);\r\n this.paths.push(lineElem);\r\n\r\n if (gradient == null) {\r\n gradient = this.createGradient(line, fromX, fromY, toX, toY);\r\n }\r\n lineElem.setAttributeNS(null, 'stroke', `url('#${gradient}')`);\r\n }\r\n\r\n /**\r\n * Draw a point.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // first create a mask\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', x + offsetX);\r\n mask.setAttributeNS(null, 'cy', y + offsetY);\r\n mask.setAttributeNS(null, 'r', '1.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // now create the point\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + offsetX);\r\n point.setAttributeNS(null, 'cy', y + offsetY);\r\n point.setAttributeNS(null, 'r', '0.75');\r\n point.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n this.vertices.push(point);\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n pos = {\r\n x: x + offsetX,\r\n y: y + offsetY,\r\n },\r\n textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text'),\r\n writingMode = 'horizontal-tb',\r\n letterSpacing = 'normal',\r\n textOrientation = 'mixed',\r\n textDirection = 'direction: ltr;',\r\n xShift = -2,\r\n yShift = 2.5;\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', pos.x);\r\n mask.setAttributeNS(null, 'cy', pos.y);\r\n mask.setAttributeNS(null, 'r', '3.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // determine writing mode\r\n if (/up|down/.test(direction) && !isTerminal) {\r\n writingMode = 'vertical-rl';\r\n textOrientation = 'upright';\r\n letterSpacing = '-1px';\r\n }\r\n\r\n if (direction === 'down' && !isTerminal) {\r\n xShift = 0;\r\n yShift = -2;\r\n } else if (direction === 'up' && !isTerminal) {\r\n xShift = 0.5;\r\n } else if (direction === 'left') {\r\n xShift = 2;\r\n }\r\n\r\n if (direction === 'left' || (direction === 'up' && !isTerminal)) {\r\n textDirection = 'direction: rtl; unicode-bidi: bidi-override;'\r\n }\r\n\r\n // now the text element\r\n textElem.setAttributeNS(null, 'x', pos.x + xShift);\r\n textElem.setAttributeNS(null, 'y', pos.y + yShift);\r\n textElem.setAttributeNS(null, 'class', 'element');\r\n textElem.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n textElem.setAttributeNS(null, 'style', `\r\n text-anchor: start;\r\n writing-mode: ${writingMode};\r\n text-orientation: ${textOrientation};\r\n letter-spacing: ${letterSpacing};\r\n ${textDirection}\r\n `);\r\n\r\n let textNode = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n // special case for element names that are 2 letters\r\n if (elementName.length > 1) {\r\n let textAnchor = /up|down/.test(direction) ? 'middle' : 'start';\r\n\r\n textNode.setAttributeNS(null, 'style', `\r\n unicode-bidi: plaintext;\r\n writing-mode: lr-tb;\r\n letter-spacing: normal;\r\n text-anchor: ${textAnchor};\r\n `);\r\n }\r\n textNode.appendChild(document.createTextNode(elementName));\r\n textElem.appendChild(textNode);\r\n\r\n // Charge\r\n if (charge) {\r\n let chargeElem = this.createSubSuperScripts(getChargeText(charge), 'super');\r\n textNode.appendChild(chargeElem);\r\n }\r\n\r\n let isotopeText = '0';\r\n\r\n if (isotope > 0) {\r\n let isotopeElem = this.createSubSuperScripts(isotope.toString(), 'super');\r\n textNode.appendChild(isotopeElem);\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') &&\r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = {\r\n '0O': {\r\n element: 'O',\r\n count: 2,\r\n hydrogenCount: 0,\r\n previousElement: 'C',\r\n charge: ''\r\n }\r\n }\r\n charge = 0;\r\n }\r\n\r\n if (hydrogens > 0) {\r\n let hydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n hydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n hydrogenElem.appendChild(document.createTextNode('H'));\r\n textElem.appendChild(hydrogenElem);\r\n\r\n if (hydrogens > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogens, 'sub');\r\n hydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let element = attachedPseudoElement[key].element,\r\n elementCount = attachedPseudoElement[key].count,\r\n hydrogenCount = attachedPseudoElement[key].hydrogenCount,\r\n elementCharge = attachedPseudoElement[key].charge,\r\n pseudoElementElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoElementElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoElementElem.appendChild(document.createTextNode(element));\r\n pseudoElementElem.setAttributeNS(null, 'fill', this.themeManager.getColor(element));\r\n\r\n if (elementCharge !== 0) {\r\n let elementChargeElem = this.createSubSuperScripts(getChargeText(elementCharge), 'super');\r\n pseudoElementElem.appendChild(elementChargeElem);\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n let pseudoHydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoHydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoHydrogenElem.appendChild(document.createTextNode('H'));\r\n pseudoElementElem.appendChild(pseudoHydrogenElem);\r\n\r\n if (hydrogenCount > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogenCount, 'sub');\r\n pseudoHydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n if (elementCount > 1) {\r\n let elementCountElem = this.createSubSuperScripts(elementCount, 'sub');\r\n pseudoElementElem.appendChild(elementCountElem);\r\n }\r\n\r\n textElem.appendChild(pseudoElementElem);\r\n }\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * @param {Line} line the line object to create the wedge from\r\n */\r\n drawWedge(line) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l,\r\n end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness)),\r\n u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness)),\r\n v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness)),\r\n w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n let polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'),\r\n gradient = this.createGradient(line, l.x, l.y, r.x, r.y);\r\n polygon.setAttributeNS(null, 'points', `${t.x},${t.y} ${u.x},${u.y} ${v.x},${v.y} ${w.x},${w.y}`);\r\n polygon.setAttributeNS(null, 'fill', `url('#${gradient}')`);\r\n this.paths.push(polygon);\r\n }\r\n}\r\n\r\nmodule.exports = SvgWrapper;","class ThemeManager {\r\n constructor(colors, theme) {\r\n this.colors = colors;\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n if (key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.theme) {\r\n return this.theme[key];\r\n }\r\n }\r\n\r\n return this.theme['C'];\r\n }\r\n\r\n /**\r\n * Sets the theme to the specified string if it exists. If it does not, this\r\n * does nothing.\r\n *\r\n * @param {String} theme the name of the theme to switch to\r\n */\r\n setTheme(theme) {\r\n if (this.colors.hasOwnProperty(theme)) {\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n // TODO: this probably should notify those who are watching this theme\r\n // manager that the theme has changed so that colors can be changed\r\n // on the fly\r\n }\r\n}\r\n\r\nmodule.exports = ThemeManager;","/**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\nfunction getChargeText(charge) {\r\n console.log('in the utility version of getChargeText');\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n getChargeText,\r\n}","//@ts-check\r\n\r\n/** \r\n * A class representing a 2D vector.\r\n * \r\n * @property {Number} x The x component of the vector.\r\n * @property {Number} y The y component of the vector.\r\n */\r\nclass Vector2 {\r\n /**\r\n * The constructor of the class Vector2.\r\n *\r\n * @param {(Number|Vector2)} x The initial x coordinate value or, if the single argument, a Vector2 object.\r\n * @param {Number} y The initial y coordinate value.\r\n */\r\n constructor(x, y) {\r\n if (arguments.length == 0) {\r\n this.x = 0;\r\n this.y = 0;\r\n } else if (arguments.length == 1) {\r\n this.x = x.x;\r\n this.y = x.y;\r\n } else {\r\n this.x = x;\r\n this.y = y;\r\n }\r\n }\r\n\r\n /**\r\n * Clones this vector and returns the clone.\r\n *\r\n * @returns {Vector2} The clone of this vector.\r\n */\r\n clone() {\r\n return new Vector2(this.x, this.y);\r\n }\r\n\r\n /**\r\n * Returns a string representation of this vector.\r\n *\r\n * @returns {String} A string representation of this vector.\r\n */\r\n toString() {\r\n return '(' + this.x + ',' + this.y + ')';\r\n }\r\n\r\n /**\r\n * Add the x and y coordinate values of a vector to the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n add(vec) {\r\n this.x += vec.x;\r\n this.y += vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Subtract the x and y coordinate values of a vector from the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n subtract(vec) {\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Divide the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n divide(scalar) {\r\n this.x /= scalar;\r\n this.y /= scalar;\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Multiply the x and y coordinate values of this vector by the values of another vector.\r\n *\r\n * @param {Vector2} v A vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiply(v) {\r\n this.x *= v.x;\r\n this.y *= v.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Multiply the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiplyScalar(scalar) {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Inverts this vector. Same as multiply(-1.0).\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n invert() {\r\n this.x = -this.x;\r\n this.y = -this.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vector in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n angle() {\r\n return Math.atan2(this.y, this.x);\r\n }\r\n\r\n /**\r\n * Returns the euclidean distance between this vector and another vector.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Number} The euclidean distance between the two vectors.\r\n */\r\n distance(vec) {\r\n return Math.sqrt((vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y));\r\n }\r\n\r\n /**\r\n * Returns the squared euclidean distance between this vector and another vector. When only the relative distances of a set of vectors are needed, this is is less expensive than using distance(vec).\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} The squared euclidean distance of the two vectors.\r\n */\r\n distanceSq(vec) {\r\n return (vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to the coordinate system.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to the coordinate system.\r\n */\r\n clockwise(vec) {\r\n let a = this.y * vec.x;\r\n let b = this.x * vec.y;\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to an arbitrary third vector.\r\n *\r\n * @param {Vector2} center The central vector.\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to an arbitrary third vector.\r\n */\r\n relativeClockwise(center, vec) {\r\n let a = (this.y - center.y) * (vec.x - center.x);\r\n let b = (this.x - center.x) * (vec.y - center.y);\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Rotates this vector by a given number of radians around the origin of the coordinate system.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotate(angle) {\r\n let tmp = new Vector2(0, 0);\r\n let cosAngle = Math.cos(angle);\r\n let sinAngle = Math.sin(angle);\r\n\r\n tmp.x = this.x * cosAngle - this.y * sinAngle;\r\n tmp.y = this.x * sinAngle + this.y * cosAngle;\r\n \r\n this.x = tmp.x;\r\n this.y = tmp.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this vector around another vector.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @param {Vector2} vec The vector which is used as the rotational center.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateAround(angle, vec) {\r\n let s = Math.sin(angle);\r\n let c = Math.cos(angle);\r\n\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n let x = this.x * c - this.y * s;\r\n let y = this.x * s + this.y * c;\r\n\r\n this.x = x + vec.x;\r\n this.y = y + vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate a vector around a given center to the same angle as another vector (so that the two vectors and the center are in a line, with both vectors on one side of the center), keeps the distance from this vector to the center.\r\n *\r\n * @param {Vector2} vec The vector to rotate this vector to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} [offsetAngle=0.0] An additional amount of radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateTo(vec, center, offsetAngle = 0.0) {\r\n // Problem if this is first position\r\n this.x += 0.001;\r\n this.y -= 0.001;\r\n\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n\r\n this.rotateAround(angle + offsetAngle, center);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates the vector away from a specified vector around a center.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n */\r\n rotateAwayFrom(vec, center, angle) {\r\n this.rotateAround(angle, center);\r\n \r\n let distSqA = this.distanceSq(vec);\r\n \r\n this.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = this.distanceSq(vec);\r\n\r\n // If it was rotated towards the other vertex, rotate in other direction by same amount.\r\n if (distSqB < distSqA) {\r\n this.rotateAround(2.0 * angle, center);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector away from a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateAwayFromAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB < distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector towards a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated towards to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateTowardsAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB > distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the angles between this vector and another vector around a common center of rotation.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @param {Vector2} center The center of rotation.\r\n * @returns {Number} The angle between this vector and another vector around a center of rotation in radians.\r\n */\r\n getRotateToAngle(vec, center) {\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n \r\n return Number.isNaN(angle) ? 0.0 : angle;\r\n }\r\n\r\n /**\r\n * Checks whether a vector lies within a polygon spanned by a set of vectors.\r\n *\r\n * @param {Vector2[]} polygon An array of vectors spanning the polygon.\r\n * @returns {Boolean} A boolean indicating whether or not this vector is within a polygon.\r\n */\r\n isInPolygon(polygon) {\r\n let inside = false;\r\n\r\n // Its not always a given, that the polygon is convex (-> sugars)\r\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\r\n if (((polygon[i].y > this.y) != (polygon[j].y > this.y)) &&\r\n (this.x < (polygon[j].x - polygon[i].x) * (this.y - polygon[i].y) /\r\n (polygon[j].y - polygon[i].y) + polygon[i].x)) {\r\n inside = !inside;\r\n }\r\n }\r\n\r\n\r\n return inside;\r\n }\r\n\r\n /**\r\n * Returns the length of this vector.\r\n *\r\n * @returns {Number} The length of this vector.\r\n */\r\n length() {\r\n return Math.sqrt((this.x * this.x) + (this.y * this.y));\r\n }\r\n\r\n /**\r\n * Returns the square of the length of this vector.\r\n *\r\n * @returns {Number} The square of the length of this vector.\r\n */\r\n lengthSq() {\r\n return (this.x * this.x) + (this.y * this.y);\r\n }\r\n\r\n /**\r\n * Normalizes this vector.\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n normalize() {\r\n this.divide(this.length());\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns a normalized copy of this vector.\r\n *\r\n * @returns {Vector2} A normalized copy of this vector.\r\n */\r\n normalized() {\r\n return Vector2.divideScalar(this, this.length());\r\n }\r\n\r\n /**\r\n * Calculates which side of a line spanned by two vectors this vector is.\r\n *\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} A number indicating the side of this vector, given a line spanned by two other vectors.\r\n */\r\n whichSide(vecA, vecB) {\r\n return (this.x - vecA.x) * (vecB.y - vecA.y) - (this.y - vecA.y) * (vecB.x - vecA.x);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is on the same side of a line spanned by two vectors as another vector.\r\n *\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @param {Vector2} vecC A vector to check whether or not it is on the same side as this vector.\r\n * @returns {Boolean} Returns a boolean indicating whether or not this vector is on the same side as another vector.\r\n */\r\n sameSideAs(vecA, vecB, vecC) {\r\n let d = this.whichSide(vecA, vecB);\r\n let dRef = vecC.whichSide(vecA, vecB);\r\n\r\n return d < 0 && dRef < 0 || d == 0 && dRef == 0 || d > 0 && dRef > 0;\r\n }\r\n\r\n /**\r\n * Adds two vectors and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A summand.\r\n * @param {Vector2} vecB A summand.\r\n * @returns {Vector2} Returns the sum of two vectors.\r\n */\r\n static add(vecA, vecB) {\r\n return new Vector2(vecA.x + vecB.x, vecA.y + vecB.y);\r\n }\r\n\r\n /**\r\n * Subtracts one vector from another and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The minuend.\r\n * @param {Vector2} vecB The subtrahend.\r\n * @returns {Vector2} Returns the difference of two vectors.\r\n */\r\n static subtract(vecA, vecB) {\r\n return new Vector2(vecA.x - vecB.x, vecA.y - vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiply(vecA, vecB) {\r\n return new Vector2(vecA.x * vecB.x, vecA.y * vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vec A vector.\r\n * @param {Number} scalar A scalar.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiplyScalar(vec, scalar) {\r\n return new Vector2(vec.x, vec.y).multiplyScalar(scalar);\r\n }\r\n\r\n /**\r\n * Returns the midpoint of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2} The midpoint of the line spanned by two vectors.\r\n */\r\n static midpoint(vecA, vecB) {\r\n return new Vector2((vecA.x + vecB.x) / 2, (vecA.y + vecB.y) / 2);\r\n }\r\n\r\n /**\r\n * Returns the normals of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two normals, each represented by a vector.\r\n */\r\n static normals(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n new Vector2(-delta.y, delta.x),\r\n new Vector2(delta.y, -delta.x)\r\n ];\r\n }\r\n\r\n /**\r\n * Returns the unit (normalized normal) vectors of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two unit vectors.\r\n */\r\n static units(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n (new Vector2(-delta.y, delta.x)).normalize(),\r\n (new Vector2(delta.y, -delta.x)).normalize()\r\n ];\r\n }\r\n\r\n /**\r\n * Divides a vector by another vector and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Vector2} vecB The divisor.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divide(vecA, vecB) {\r\n return new Vector2(vecA.x / vecB.x, vecA.y / vecB.y);\r\n }\r\n\r\n /**\r\n * Divides a vector by a scalar and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Number} s The scalar.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divideScalar(vecA, s) {\r\n return new Vector2(vecA.x / s, vecA.y / s);\r\n }\r\n\r\n /**\r\n * Returns the dot product of two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The dot product of two vectors.\r\n */\r\n static dot(vecA, vecB) {\r\n return vecA.x * vecB.x + vecA.y * vecB.y;\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The angle between two vectors in radians.\r\n */\r\n static angle(vecA, vecB) {\r\n let dot = Vector2.dot(vecA, vecB);\r\n\r\n return Math.acos(dot / (vecA.length() * vecB.length()));\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors based on a third vector in between.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A (central) vector.\r\n * @param {Vector2} vecC A vector.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static threePointangle(vecA, vecB, vecC) {\r\n let ab = Vector2.subtract(vecB, vecA);\r\n let bc = Vector2.subtract(vecC, vecB);\r\n let abLength = vecA.distance(vecB);\r\n let bcLength = vecB.distance(vecC);\r\n\r\n return Math.acos(Vector2.dot(ab, bc) / (abLength * bcLength));\r\n }\r\n \r\n /**\r\n * Returns the scalar projection of a vector on another vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The vector to be projected.\r\n * @param {Vector2} vecB The vector to be projection upon.\r\n * @returns {Number} The scalar component.\r\n */\r\n static scalarProjection(vecA, vecB) {\r\n let unit = vecB.normalized();\r\n \r\n return Vector2.dot(vecA, unit);\r\n }\r\n\r\n /**\r\n * Returns the average vector (normalized) of the input vectors.\r\n *\r\n * @static\r\n * @param {Array} vecs An array containing vectors.\r\n * @returns {Vector2} The resulting vector (normalized).\r\n */\r\n static averageDirection(vecs) {\r\n let avg = new Vector2(0.0, 0.0);\r\n\r\n for (var i = 0; i < vecs.length; i++) {\r\n let vec = vecs[i];\r\n avg.add(vec);\r\n }\r\n\r\n return avg.normalize();\r\n }\r\n}\r\n\r\nmodule.exports = Vector2;","//@ts-check\r\nconst MathHelper = require('./MathHelper')\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Atom = require('./Atom')\r\nconst VertexState = require('./VertexState')\r\n\r\n/** \r\n * A class representing a vertex.\r\n * \r\n * @property {Number} id The id of this vertex.\r\n * @property {Atom} value The atom associated with this vertex.\r\n * @property {Vector2} position The position of this vertex.\r\n * @property {Vector2} previousPosition The position of the previous vertex.\r\n * @property {Number|null} parentVertexId The id of the previous vertex.\r\n * @property {Number[]} children The ids of the children of this vertex.\r\n * @property {Number[]} spanningTreeChildren The ids of the children of this vertex as defined in the spanning tree defined by the SMILES.\r\n * @property {Number[]} edges The ids of edges associated with this vertex.\r\n * @property {Boolean} positioned A boolean indicating whether or not this vertex has been positioned.\r\n * @property {Number} angle The angle of this vertex.\r\n * @property {Number} dir The direction of this vertex.\r\n * @property {Number} neighbourCount The number of neighbouring vertices.\r\n * @property {Number[]} neighbours The vertex ids of neighbouring vertices.\r\n * @property {String[]} neighbouringElements The element symbols associated with neighbouring vertices.\r\n * @property {Boolean} forcePositioned A boolean indicating whether or not this vertex was positioned using a force-based approach.\r\n * @property {Number} vertexState enum of VertexState for DFS.\r\n */\r\n\r\nclass Vertex {\r\n /**\r\n * The constructor for the class Vertex.\r\n *\r\n * @param {Atom} value The value associated with this vertex.\r\n * @param {Number} [x=0] The initial x coordinate of the positional vector of this vertex.\r\n * @param {Number} [y=0] The initial y coordinate of the positional vector of this vertex.\r\n */\r\n constructor(value, x = 0, y = 0) {\r\n this.id = null;\r\n this.value = value;\r\n this.position = new Vector2(x ? x : 0, y ? y : 0);\r\n this.previousPosition = new Vector2(0, 0);\r\n this.parentVertexId = null;\r\n this.children = Array();\r\n this.spanningTreeChildren = Array();\r\n this.edges = Array();\r\n this.positioned = false;\r\n this.angle = null;\r\n this.dir = 1.0;\r\n this.neighbourCount = 0;\r\n this.neighbours = Array();\r\n this.neighbouringElements = Array();\r\n this.forcePositioned = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n this.component = -1;\r\n this.digits = [];\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex.\r\n * \r\n * @param {Number} x The x component of the coordinates.\r\n * @param {Number} y The y component of the coordinates.\r\n * \r\n */\r\n setPosition(x, y) {\r\n this.position.x = x;\r\n this.position.y = y;\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex from a Vector2.\r\n * \r\n * @param {Vector2} v A 2D vector.\r\n * \r\n */\r\n setPositionFromVector(v) {\r\n this.position.x = v.x;\r\n this.position.y = v.y;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n */\r\n addChild(vertexId) {\r\n this.children.push(vertexId);\r\n this.neighbours.push(vertexId);\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex as the second child of the neighbours array,\r\n * except this vertex is the first vertex of the SMILE string, then it is added as the first.\r\n * This is used to get the correct ordering of neighbours for parity calculations.\r\n * If a hydrogen is implicitly attached to the chiral center, insert as the third child.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n * @param {Number} ringbondIndex The index of the ringbond.\r\n */\r\n addRingbondChild(vertexId, ringbondIndex) {\r\n this.children.push(vertexId);\r\n\r\n if (this.value.bracket) {\r\n let index = 1;\r\n\r\n if (this.id === 0 && this.value.bracket.hcount === 0) {\r\n index = 0;\r\n }\r\n \r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 0) {\r\n index = 2;\r\n }\r\n\r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 2;\r\n } else {\r\n index = 3;\r\n }\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 0) {\r\n index = 1;\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 1;\r\n } else {\r\n index = 2;\r\n }\r\n }\r\n \r\n this.neighbours.splice(index, 0, vertexId);\r\n } else {\r\n this.neighbours.push(vertexId);\r\n }\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Set the vertex id of the parent.\r\n * \r\n * @param {Number} parentVertexId The parents vertex id.\r\n */\r\n setParentVertexId(parentVertexId) {\r\n this.neighbourCount++;\r\n this.parentVertexId = parentVertexId;\r\n this.neighbours.push(parentVertexId);\r\n }\r\n\r\n /**\r\n * Returns true if this vertex is terminal (has no parent or child vertices), otherwise returns false. Always returns true if associated value has property hasAttachedPseudoElements set to true.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not this vertex is terminal.\r\n */\r\n isTerminal() {\r\n if (this.value.hasAttachedPseudoElements) {\r\n return true;\r\n }\r\n\r\n return (this.parentVertexId === null && this.children.length < 2) || this.children.length === 0;\r\n }\r\n\r\n /**\r\n * Clones this vertex and returns the clone.\r\n *\r\n * @returns {Vertex} A clone of this vertex.\r\n */\r\n clone() {\r\n let clone = new Vertex(this.value, this.position.x, this.position.y);\r\n clone.id = this.id;\r\n clone.previousPosition = new Vector2(this.previousPosition.x, this.previousPosition.y);\r\n clone.parentVertexId = this.parentVertexId;\r\n clone.children = ArrayHelper.clone(this.children);\r\n clone.spanningTreeChildren = ArrayHelper.clone(this.spanningTreeChildren);\r\n clone.edges = ArrayHelper.clone(this.edges);\r\n clone.positioned = this.positioned;\r\n clone.angle = this.angle;\r\n clone.forcePositioned = this.forcePositioned;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns true if this vertex and the supplied vertex both have the same id, else returns false.\r\n *\r\n * @param {Vertex} vertex The vertex to check.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices have the same id.\r\n */\r\n equals(vertex) {\r\n return this.id === vertex.id;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vertexes positional vector. If a reference vector is supplied in relations to this vector, else in relations to the coordinate system.\r\n *\r\n * @param {Vector2} [referenceVector=null] - The reference vector.\r\n * @param {Boolean} [returnAsDegrees=false] - If true, returns angle in degrees, else in radians.\r\n * @returns {Number} The angle of this vertex.\r\n */\r\n getAngle(referenceVector = null, returnAsDegrees = false) {\r\n let u = null;\r\n\r\n if (!referenceVector) {\r\n u = Vector2.subtract(this.position, this.previousPosition);\r\n } else {\r\n u = Vector2.subtract(this.position, referenceVector);\r\n }\r\n\r\n if (returnAsDegrees) {\r\n return MathHelper.toDeg(u.angle());\r\n }\r\n\r\n return u.angle();\r\n }\r\n\r\n /**\r\n * Returns the suggested text direction when text is added at the position of this vertex.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @returns {String} The suggested direction of the text.\r\n */\r\n getTextDirection(vertices) {\r\n let neighbours = this.getDrawnNeighbours(vertices);\r\n let angles = Array();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n angles.push(this.getAngle(vertices[neighbours[i]].position));\r\n }\r\n\r\n let textAngle = MathHelper.meanAngle(angles);\r\n\r\n // Round to 0, 90, 180 or 270 degree\r\n let halfPi = Math.PI / 2.0;\r\n textAngle = Math.round(Math.round(textAngle / halfPi) * halfPi);\r\n\r\n if (textAngle === 2) {\r\n return 'down';\r\n } else if (textAngle === -2) {\r\n return 'up';\r\n } else if (textAngle === 0 || textAngle === -0) {\r\n return 'right'; // is checking for -0 necessary?\r\n } else if (textAngle === 3 || textAngle === -3) {\r\n return 'left';\r\n } else {\r\n return 'down'; // default to down\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices.\r\n *\r\n * @param {Number} [vertexId=null] If a value is supplied, the vertex with this id is excluded from the returned indices.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices.\r\n */\r\n getNeighbours(vertexId = null) {\r\n if (vertexId === null) {\r\n return this.neighbours.slice();\r\n }\r\n\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (this.neighbours[i] !== vertexId) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices that will be drawn (vertex.value.isDrawn === true).\r\n * \r\n * @param {Vertex[]} vertices An array containing the vertices associated with the current molecule.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices that will be drawn.\r\n */\r\n getDrawnNeighbours(vertices) {\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (vertices[this.neighbours[i]].value.isDrawn) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns the number of neighbours of this vertex.\r\n *\r\n * @returns {Number} The number of neighbours.\r\n */\r\n getNeighbourCount() {\r\n return this.neighbourCount;\r\n }\r\n\r\n /**\r\n * Returns a list of ids of vertices neighbouring this one in the original spanning tree, excluding the ringbond connections.\r\n *\r\n * @param {Number} [vertexId=null] If supplied, the vertex with this id is excluded from the array returned.\r\n * @returns {Number[]} An array containing the ids of the neighbouring vertices.\r\n */\r\n getSpanningTreeNeighbours(vertexId = null) {\r\n let neighbours = Array();\r\n\r\n for (let i = 0; i < this.spanningTreeChildren.length; i++) {\r\n if (vertexId === undefined || vertexId != this.spanningTreeChildren[i]) {\r\n neighbours.push(this.spanningTreeChildren[i]);\r\n }\r\n }\r\n\r\n if (this.parentVertexId != null) {\r\n if (vertexId === undefined || vertexId != this.parentVertexId) {\r\n neighbours.push(this.parentVertexId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Gets the next vertex in the ring in opposide direction to the supplied vertex id.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @param {Number} ringId The id of the ring containing this vertex.\r\n * @param {Number} previousVertexId The id of the previous vertex. The next vertex will be opposite from the vertex with this id as seen from this vertex.\r\n * @returns {Number} The id of the next vertex in the ring.\r\n */\r\n getNextInRing(vertices, ringId, previousVertexId) {\r\n let neighbours = this.getNeighbours();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (ArrayHelper.contains(vertices[neighbours[i]].value.rings, {\r\n value: ringId\r\n }) &&\r\n neighbours[i] != previousVertexId) {\r\n return neighbours[i];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n\r\nmodule.exports = Vertex;","//@ts-check\r\n\r\nclass VertexState {\r\n\r\n /**\r\n * Enum values of Vertex State for DFS\r\n * @return {{NOT_FOUND: number, OPEN: number, CLOSED: number, FULLY_CLOSED: number}}\r\n */\r\n static get VALUES() {\r\n return { NOT_FOUND: 0, OPEN: 1, CLOSED: 2, FULLY_CLOSED: 3 };\r\n }\r\n}\r\n\r\nmodule.exports = VertexState;\r\n"]} \ No newline at end of file +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","app.js","src/ArrayHelper.js","src/Atom.js","src/CanvasWrapper.js","src/DecayPoint.js","src/DecayState.js","src/Direction.js","src/Drawer.js","src/Edge.js","src/Graph.js","src/Line.js","src/MathHelper.js","src/MutableBoolean.js","src/MutableCounter.js","src/Neighbour.js","src/Node.js","src/Parser.js","src/Ring.js","src/RingConnection.js","src/SSSR.js","src/SequenceType.js","src/SmallGraph.js","src/SvgDrawer.js","src/SvgWrapper.js","src/ThemeManager.js","src/UtilityFunctions.js","src/Vector2.js","src/Vertex.js","src/VertexState.js"],"names":[],"mappings":"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","file":"smiles-drawer.min.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i {\r\n const context = canvas.getContext('2d');\r\n context.clearRect(0, 0, canvas.width, canvas.height);\r\n })\r\n};\r\n\r\n/**\r\n* Parses the entered smiles string.\r\n*\r\n* @static\r\n* @param {String} smiles A SMILES string.\r\n* @param {Function} successCallback A callback that is called on success with the parse tree.\r\n* @param {Function} errorCallback A callback that is called with the error object on error.\r\n*/\r\nSmilesDrawer.parse = function(smiles, successCallback, errorCallback) {\r\n try {\r\n if (successCallback) {\r\n successCallback(Parser.parse(smiles));\r\n }\r\n } catch (err) {\r\n if (errorCallback) {\r\n errorCallback(err);\r\n }\r\n }\r\n};\r\n\r\nif (canUseDOM) {\r\n window.SmilesDrawer = SmilesDrawer;\r\n}\r\n\r\n// There be dragons (polyfills)\r\n\r\nif (!Array.prototype.fill) {\r\nObject.defineProperty(Array.prototype, 'fill', {\r\n value: function(value) {\r\n\r\n // Steps 1-2.\r\n if (this == null) {\r\n throw new TypeError('this is null or not defined');\r\n }\r\n\r\n var O = Object(this);\r\n\r\n // Steps 3-5.\r\n var len = O.length >>> 0;\r\n\r\n // Steps 6-7.\r\n var start = arguments[1];\r\n var relativeStart = start >> 0;\r\n\r\n // Step 8.\r\n var k = relativeStart < 0 ?\r\n Math.max(len + relativeStart, 0) :\r\n Math.min(relativeStart, len);\r\n\r\n // Steps 9-10.\r\n var end = arguments[2];\r\n var relativeEnd = end === undefined ?\r\n len : end >> 0;\r\n\r\n // Step 11.\r\n var final = relativeEnd < 0 ?\r\n Math.max(len + relativeEnd, 0) :\r\n Math.min(relativeEnd, len);\r\n\r\n // Step 12.\r\n while (k < final) {\r\n O[k] = value;\r\n k++;\r\n }\r\n\r\n // Step 13.\r\n return O;\r\n }\r\n});\r\n}\r\n\r\nmodule.exports = SmilesDrawer;","//@ts-check\r\n\r\n/** \r\n * A static class containing helper functions for array-related tasks. \r\n */\r\nclass ArrayHelper {\r\n /**\r\n * Clone an array or an object. If an object is passed, a shallow clone will be created.\r\n *\r\n * @static\r\n * @param {*} arr The array or object to be cloned.\r\n * @returns {*} A clone of the array or object.\r\n */\r\n static clone(arr) {\r\n let out = Array.isArray(arr) ? Array() : {};\r\n \r\n for (let key in arr) {\r\n let value = arr[key];\r\n \r\n if (typeof value.clone === 'function') {\r\n out[key] = value.clone();\r\n }\r\n else {\r\n out[key] = (typeof value === 'object') ? ArrayHelper.clone(value) : value;\r\n }\r\n }\r\n \r\n return out;\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not the two arrays contain the same elements.\r\n * Only supports 1d, non-nested arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not the two arrays contain the same elements.\r\n */\r\n static equals(arrA, arrB) {\r\n if (arrA.length !== arrB.length) {\r\n return false;\r\n }\r\n\r\n let tmpA = arrA.slice().sort();\r\n let tmpB = arrB.slice().sort();\r\n\r\n for (let i = 0; i < tmpA.length; i++) {\r\n if (tmpA[i] !== tmpB[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns a string representation of an array. If the array contains objects with an id property, the id property is printed for each of the elements.\r\n *\r\n * @static\r\n * @param {Object[]} arr An array.\r\n * @param {*} arr[].id If the array contains an object with the property 'id', the properties value is printed. Else, the array elements value is printend.\r\n * @returns {String} A string representation of the array.\r\n */\r\n static print(arr) {\r\n if (arr.length == 0) {\r\n return '';\r\n }\r\n\r\n let s = '(';\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n s += arr[i].id ? arr[i].id + ', ' : arr[i] + ', ';\r\n }\r\n\r\n s = s.substring(0, s.length - 2);\r\n\r\n return s + ')';\r\n }\r\n\r\n /**\r\n * Run a function for each element in the array. The element is supplied as an argument for the callback function\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Function} callback The callback function that is called for each element.\r\n */\r\n static each(arr, callback) {\r\n for (let i = 0; i < arr.length; i++) {\r\n callback(arr[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Return the array element from an array containing objects, where a property of the object is set to a given value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {(String|Number)} property A property contained within an object in the array.\r\n * @param {(String|Number)} value The value of the property.\r\n * @returns {*} The array element matching the value.\r\n */\r\n static get(arr, property, value) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][property] == value) {\r\n return arr[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains a given value. the options object passed as a second argument can contain three properties. value: The value to be searched for. property: The property that is to be searched for a given value. func: A function that is used as a callback to return either true or false in order to do a custom comparison.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Object} options See method description.\r\n * @param {*} options.value The value for which to check.\r\n * @param {String} [options.property=undefined] The property on which to check.\r\n * @param {Function} [options.func=undefined] A custom property function.\r\n * @returns {Boolean} A boolean whether or not the array contains a value.\r\n */\r\n static contains(arr, options) {\r\n if (!options.property && !options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] == options.value) {\r\n return true;\r\n }\r\n }\r\n } else if (options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (options.func(arr[i])) {\r\n return true;\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][options.property] == options.value) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array containing the intersection between two arrays. That is, values that are common to both arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The intersecting vlaues.\r\n */\r\n static intersection(arrA, arrB) {\r\n let intersection = [];\r\n \r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n intersection.push(arrA[i]);\r\n }\r\n }\r\n }\r\n\r\n return intersection;\r\n }\r\n\r\n /**\r\n * Returns an array of unique elements contained in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @returns {Array} An array of unique elements contained within the array supplied as an argument.\r\n */\r\n static unique(arr) {\r\n let contains = {};\r\n return arr.filter(function (i) {\r\n // using !== instead of hasOwnProperty (http://andrew.hedges.name/experiments/in/)\r\n return contains[i] !== undefined ? false : (contains[i] = true);\r\n });\r\n }\r\n\r\n /**\r\n * Count the number of occurences of a value in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be counted.\r\n * @returns {Number} The number of occurences of a value in the array.\r\n */\r\n static count(arr, value) {\r\n let count = 0;\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] === value) {\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Toggles the value of an array. If a value is not contained in an array, the array returned will contain all the values of the original array including the value. If a value is contained in an array, the array returned will contain all the values of the original array excluding the value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be toggled.\r\n * @returns {Array} The toggled array.\r\n */\r\n static toggle(arr, value) {\r\n let newArr = Array();\r\n\r\n let removed = false;\r\n for (let i = 0; i < arr.length; i++) {\r\n // Do not copy value if it exists\r\n if (arr[i] !== value) {\r\n newArr.push(arr[i]);\r\n } else {\r\n // The element was not copied to the new array, which\r\n // means it was removed\r\n removed = true;\r\n }\r\n }\r\n\r\n // If the element was not removed, then it was not in the array\r\n // so add it\r\n if (!removed) {\r\n newArr.push(value);\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n /**\r\n * Remove a value from an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} A new array with the element with a given value removed.\r\n */\r\n static remove(arr, value) {\r\n let tmp = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] !== value) {\r\n tmp.push(arr[i]);\r\n }\r\n }\r\n\r\n return tmp;\r\n }\r\n\r\n /**\r\n * Remove a value from an array with unique values.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} An array with the element with a given value removed.\r\n */\r\n static removeUnique(arr, value) {\r\n let index = arr.indexOf(value);\r\n\r\n if (index > -1) {\r\n arr.splice(index, 1);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Remove all elements contained in one array from another array.\r\n *\r\n * @static\r\n * @param {Array} arrA The array to be filtered.\r\n * @param {Array} arrB The array containing elements that will be removed from the other array.\r\n * @returns {Array} The filtered array.\r\n */\r\n static removeAll(arrA, arrB) {\r\n return arrA.filter(function (item) {\r\n return arrB.indexOf(item) === -1;\r\n });\r\n }\r\n\r\n /**\r\n * Merges two arrays and returns the result. The first array will be appended to the second array.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The merged array.\r\n */\r\n static merge(arrA, arrB) {\r\n let arr = new Array(arrA.length + arrB.length);\r\n\r\n for (let i = 0; i < arrA.length; i++) {\r\n arr[i] = arrA[i];\r\n }\r\n\r\n for (let i = 0; i < arrB.length; i++) {\r\n arr[arrA.length + i] = arrB[i];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains all the elements of another array, without regard to the order.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not both array contain the same elements.\r\n */\r\n static containsAll(arrA, arrB) {\r\n let containing = 0;\r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n containing++;\r\n }\r\n }\r\n }\r\n\r\n return containing === arrB.length;\r\n }\r\n \r\n /**\r\n * Sort an array of atomic number information. Where the number is indicated as x, x.y, x.y.z, ...\r\n *\r\n * @param {Object[]} arr An array of vertex ids with their associated atomic numbers.\r\n * @param {Number} arr[].vertexId A vertex id.\r\n * @param {String} arr[].atomicNumber The atomic number associated with the vertex id.\r\n * @returns {Object[]} The array sorted by atomic number. Example of an array entry: { atomicNumber: 2, vertexId: 5 }.\r\n */\r\n static sortByAtomicNumberDesc(arr) {\r\n let map = arr.map(function(e, i) {\r\n return { index: i, value: e.atomicNumber.split('.').map(Number) };\r\n });\r\n\r\n map.sort(function(a, b) {\r\n let min = Math.min(b.value.length, a.value.length);\r\n let i = 0;\r\n \r\n while(i < min && b.value[i] === a.value[i]) {\r\n i++;\r\n }\r\n\r\n return i === min ? b.value.length - a.value.length : b.value[i] - a.value[i];\r\n });\r\n\r\n return map.map(function(e) {\r\n return arr[e.index];\r\n });\r\n }\r\n\r\n /**\r\n * Copies a an n-dimensional array.\r\n * \r\n * @param {Array} arr The array to be copied.\r\n * @returns {Array} The copy.\r\n */\r\n static deepCopy(arr) {\r\n let newArr = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n let item = arr[i];\r\n\r\n if (item instanceof Array) {\r\n newArr[i] = ArrayHelper.deepCopy(item);\r\n } else {\r\n newArr[i] = item;\r\n }\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = ArrayHelper;","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper');\r\n\r\n/** \r\n * A class representing an atom.\r\n * \r\n * @property {String} element The element symbol of this atom. Single-letter symbols are always uppercase. Examples: H, C, F, Br, Si, ...\r\n * @property {Boolean} drawExplicit A boolean indicating whether or not this atom is drawn explicitly (for example, a carbon atom). This overrides the default behaviour.\r\n * @property {Object[]} ringbonds An array containing the ringbond ids and bond types as specified in the original SMILE.\r\n * @property {String} branchBond The branch bond as defined in the SMILES.\r\n * @property {Number} ringbonds[].id The ringbond id as defined in the SMILES.\r\n * @property {String} ringbonds[].bondType The bond type of the ringbond as defined in the SMILES.\r\n * @property {Number[]} rings The ids of rings which contain this atom.\r\n * @property {String} bondType The bond type associated with this array. Examples: -, =, #, ...\r\n * @property {Boolean} isBridge A boolean indicating whether or not this atom is part of a bridge in a bridged ring (contained by the largest ring).\r\n * @property {Boolean} isBridgeNode A boolean indicating whether or not this atom is a bridge node (a member of the largest ring in a bridged ring which is connected to a bridge-atom).\r\n * @property {Number[]} originalRings Used to back up rings when they are replaced by a bridged ring.\r\n * @property {Number} bridgedRing The id of the bridged ring if the atom is part of a bridged ring.\r\n * @property {Number[]} anchoredRings The ids of the rings that are anchored to this atom. The centers of anchored rings are translated when this atom is translated.\r\n * @property {Object} bracket If this atom is defined as a bracket atom in the original SMILES, this object contains all the bracket information. Example: { hcount: {Number}, charge: ['--', '-', '+', '++'], isotope: {Number} }.\r\n * @property {Number} plane Specifies on which \"plane\" the atoms is in stereochemical deptictions (-1 back, 0 middle, 1 front).\r\n * @property {Object[]} attachedPseudoElements A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @property {String} attachedPseudoElement[].element The element symbol.\r\n * @property {Number} attachedPseudoElement[].count The number of occurences that match the key.\r\n * @property {Number} attachedPseudoElement[].hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n * @property {Boolean} hasAttachedPseudoElements A boolean indicating whether or not this attom will be drawn with an attached pseudo element or concatinated elements.\r\n * @property {Boolean} isDrawn A boolean indicating whether or not this atom is drawn. In contrast to drawExplicit, the bond is drawn neither.\r\n * @property {Boolean} isConnectedToRing A boolean indicating whether or not this atom is directly connected (but not a member of) a ring.\r\n * @property {String[]} neighbouringElements An array containing the element symbols of neighbouring atoms.\r\n * @property {Boolean} isPartOfAromaticRing A boolean indicating whether or not this atom is part of an explicitly defined aromatic ring. Example: c1ccccc1.\r\n * @property {Number} bondCount The number of bonds in which this atom is participating.\r\n * @property {String} chirality The chirality of this atom if it is a stereocenter (R or S).\r\n * @property {Number} priority The priority of this atom acording to the CIP rules, where 0 is the highest priority.\r\n * @property {Boolean} mainChain A boolean indicating whether or not this atom is part of the main chain (used for chirality).\r\n * @property {String} hydrogenDirection The direction of the hydrogen, either up or down. Only for stereocenters with and explicit hydrogen.\r\n * @property {Number} subtreeDepth The depth of the subtree coming from a stereocenter.\r\n */\r\nclass Atom {\r\n /**\r\n * The constructor of the class Atom.\r\n *\r\n * @param {String} element The one-letter code of the element.\r\n * @param {String} [bondType='-'] The type of the bond associated with this atom.\r\n */\r\n constructor(element, bondType = '-') {\r\n this.element = element.length === 1 ? element.toUpperCase() : element;\r\n this.drawExplicit = false;\r\n this.ringbonds = Array();\r\n this.rings = Array();\r\n this.bondType = bondType;\r\n this.branchBond = null;\r\n this.isBridge = false;\r\n this.isBridgeNode = false;\r\n this.originalRings = Array();\r\n this.bridgedRing = null;\r\n this.anchoredRings = Array();\r\n this.bracket = null;\r\n this.plane = 0;\r\n this.attachedPseudoElements = {};\r\n this.hasAttachedPseudoElements = false;\r\n this.isDrawn = true;\r\n this.isConnectedToRing = false;\r\n this.neighbouringElements = Array();\r\n this.isPartOfAromaticRing = element !== this.element;\r\n this.bondCount = 0;\r\n this.chirality = '';\r\n this.isStereoCenter = false;\r\n this.priority = 0;\r\n this.mainChain = false;\r\n this.hydrogenDirection = 'down';\r\n this.subtreeDepth = 1;\r\n this.hasHydrogen = false;\r\n }\r\n\r\n /**\r\n * Adds a neighbouring element to this atom.\r\n * \r\n * @param {String} element A string representing an element.\r\n */\r\n addNeighbouringElement(element) {\r\n this.neighbouringElements.push(element);\r\n }\r\n\r\n /**\r\n * Attaches a pseudo element (e.g. Ac) to the atom.\r\n * @param {String} element The element identifier (e.g. Br, C, ...).\r\n * @param {String} previousElement The element that is part of the main chain (not the terminals that are converted to the pseudo element or concatinated).\r\n * @param {Number} [hydrogenCount=0] The number of hydrogens for the element.\r\n * @param {Number} [charge=0] The charge for the element.\r\n */\r\n attachPseudoElement(element, previousElement, hydrogenCount = 0, charge = 0) {\r\n if (hydrogenCount === null) {\r\n hydrogenCount = 0;\r\n }\r\n\r\n if (charge === null) {\r\n charge = 0;\r\n }\r\n\r\n let key = hydrogenCount + element + charge;\r\n\r\n if (this.attachedPseudoElements[key]) {\r\n this.attachedPseudoElements[key].count += 1;\r\n } else {\r\n this.attachedPseudoElements[key] = {\r\n element: element,\r\n count: 1,\r\n hydrogenCount: hydrogenCount,\r\n previousElement: previousElement,\r\n charge: charge\r\n };\r\n }\r\n\r\n this.hasAttachedPseudoElements = true;\r\n }\r\n\r\n /**\r\n * Returns the attached pseudo elements sorted by hydrogen count (ascending).\r\n *\r\n * @returns {Object} The sorted attached pseudo elements.\r\n */\r\n getAttachedPseudoElements() {\r\n let ordered = {};\r\n let that = this;\r\n\r\n Object.keys(this.attachedPseudoElements).sort().forEach(function (key) {\r\n ordered[key] = that.attachedPseudoElements[key];\r\n });\r\n\r\n return ordered;\r\n }\r\n\r\n /**\r\n * Returns the number of attached pseudo elements.\r\n *\r\n * @returns {Number} The number of attached pseudo elements.\r\n */\r\n getAttachedPseudoElementsCount() {\r\n return Object.keys(this.attachedPseudoElements).length;\r\n }\r\n\r\n /**\r\n * Returns whether this atom is a heteroatom (not C and not H).\r\n *\r\n * @returns {Boolean} A boolean indicating whether this atom is a heteroatom.\r\n */\r\n isHeteroAtom() {\r\n return this.element !== 'C' && this.element !== 'H';\r\n }\r\n\r\n /**\r\n * Defines this atom as the anchor for a ring. When doing repositionings of the vertices and the vertex associated with this atom is moved, the center of this ring is moved as well.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n addAnchoredRing(ringId) {\r\n if (!ArrayHelper.contains(this.anchoredRings, {\r\n value: ringId\r\n })) {\r\n this.anchoredRings.push(ringId);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of ringbonds (breaks in rings to generate the MST of the smiles) within this atom is connected to.\r\n *\r\n * @returns {Number} The number of ringbonds this atom is connected to.\r\n */\r\n getRingbondCount() {\r\n return this.ringbonds.length;\r\n }\r\n\r\n /**\r\n * Backs up the current rings.\r\n */\r\n backupRings() {\r\n this.originalRings = Array(this.rings.length);\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings[i] = this.rings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recent backed up rings.\r\n */\r\n restoreRings() {\r\n this.rings = Array(this.originalRings.length);\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings[i] = this.originalRings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not two atoms share a common ringbond id. A ringbond is a break in a ring created when generating the spanning tree of a structure.\r\n *\r\n * @param {Atom} atomA An atom.\r\n * @param {Atom} atomB An atom.\r\n * @returns {Boolean} A boolean indicating whether or not two atoms share a common ringbond.\r\n */\r\n haveCommonRingbond(atomA, atomB) {\r\n for (let i = 0; i < atomA.ringbonds.length; i++) {\r\n for (let j = 0; j < atomB.ringbonds.length; j++) {\r\n if (atomA.ringbonds[i].id == atomB.ringbonds[j].id) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not the neighbouring elements of this atom equal the supplied array.\r\n * \r\n * @param {String[]} arr An array containing all the elements that are neighbouring this atom. E.g. ['C', 'O', 'O', 'N']\r\n * @returns {Boolean} A boolean indicating whether or not the neighbours match the supplied array of elements.\r\n */\r\n neighbouringElementsEqual(arr) {\r\n if (arr.length !== this.neighbouringElements.length) {\r\n return false;\r\n }\r\n\r\n arr.sort();\r\n this.neighbouringElements.sort();\r\n\r\n for (var i = 0; i < this.neighbouringElements.length; i++) {\r\n if (arr[i] !== this.neighbouringElements[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the atomic number of this atom.\r\n * \r\n * @returns {Number} The atomic number of this atom.\r\n */\r\n getAtomicNumber() {\r\n return Atom.atomicNumbers[this.element];\r\n }\r\n\r\n /**\r\n * Get the maximum number of bonds for this atom.\r\n * \r\n * @returns {Number} The maximum number of bonds of this atom.\r\n */\r\n getMaxBonds() {\r\n return Atom.maxBonds[this.element];\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to their maximum bonds.\r\n */\r\n static get maxBonds() {\r\n return {\r\n 'H': 1,\r\n 'C': 4,\r\n 'N': 3,\r\n 'O': 2,\r\n 'P': 3,\r\n 'S': 2,\r\n 'B': 3,\r\n 'F': 1,\r\n 'I': 1,\r\n 'Cl': 1,\r\n 'Br': 1\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic number.\r\n */\r\n static get atomicNumbers() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic mass.\r\n */\r\n static get mass() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n}\r\n\r\nmodule.exports = Atom;","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Ring = require('./Ring');\r\nconst { getChargeText } = require('./UtilityFunctions');\r\n\r\n/** \r\n * A class wrapping a canvas element.\r\n * \r\n * @property {HTMLElement} canvas The HTML element for the canvas associated with this CanvasWrapper instance.\r\n * @property {CanvasRenderingContext2D} ctx The CanvasRenderingContext2D of the canvas associated with this CanvasWrapper instance.\r\n * @property {Object} colors The colors object as defined in the SmilesDrawer options.\r\n * @property {Object} opts The SmilesDrawer options.\r\n * @property {Number} drawingWidth The width of the canvas.\r\n * @property {Number} drawingHeight The height of the canvas.\r\n * @property {Number} realWidth The width of the canvas real.\r\n * @property {Number} realHeight The height of the canvas real.\r\n * @property {Number} offsetX The horizontal offset required for centering the drawing.\r\n * @property {Number} offsetY The vertical offset required for centering the drawing.\r\n * @property {Number} fontLarge The large font size in pt.\r\n * @property {Number} fontSmall The small font size in pt.\r\n */\r\nclass CanvasWrapper {\r\n /**\r\n * The constructor for the class CanvasWrapper.\r\n *\r\n * @param {(String|HTMLElement)} target The canvas id or the canvas HTMLElement.\r\n * @param {ThemeManager} themeManager Theme manager for setting proper colors.\r\n * @param {Object} options The smiles drawer options object.\r\n */\r\n constructor(target, themeManager, options) {\r\n if (typeof target === 'string' || target instanceof String) {\r\n this.canvas = document.getElementById(target);\r\n } else {\r\n this.canvas = target;\r\n }\r\n\r\n this.ctx = this.canvas.getContext('2d');\r\n this.themeManager = themeManager;\r\n this.opts = options;\r\n this.drawingWidth = 0.0;\r\n this.drawingHeight = 0.0;\r\n this.realWidth = 0.0;\r\n this.realHeight = 0.0;\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n this.fontLarge = this.opts.fontSizeLarge + 'pt Helvetica, Arial, sans-serif';\r\n this.fontSmall = this.opts.fontSizeSmall + 'pt Helvetica, Arial, sans-serif';\r\n\r\n this.updateSize(this.opts.width, this.opts.height);\r\n\r\n this.ctx.font = this.fontLarge;\r\n this.hydrogenWidth = this.ctx.measureText('H').width;\r\n this.halfHydrogenWidth = this.hydrogenWidth / 2.0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // TODO: Find out why clear was here.\r\n // this.clear();\r\n }\r\n\r\n /**\r\n * Update the width and height of the canvas\r\n * \r\n * @param {Number} width \r\n * @param {Number} height \r\n */\r\n updateSize(width, height) {\r\n this.devicePixelRatio = window.devicePixelRatio || 1;\r\n this.backingStoreRatio = this.ctx.webkitBackingStorePixelRatio || this.ctx.mozBackingStorePixelRatio ||\r\n this.ctx.msBackingStorePixelRatio || this.ctx.oBackingStorePixelRatio ||\r\n this.ctx.backingStorePixelRatio || 1;\r\n this.ratio = this.devicePixelRatio / this.backingStoreRatio;\r\n\r\n this.canvas.width = width * this.ratio;\r\n this.canvas.height = height * this.ratio;\r\n if (this.ratio !== 1) {\r\n this.realWidth = width;\r\n this.realHeight = height;\r\n this.canvas.style.width = width + 'px';\r\n this.canvas.style.height = height + 'px';\r\n this.ctx.setTransform(this.ratio, 0, 0, this.ratio, 0, 0);\r\n }\r\n }\r\n\r\n /**\r\n * Sets a provided theme.\r\n *\r\n * @param {Object} theme A theme from the smiles drawer options.\r\n */\r\n setTheme(theme) {\r\n this.colors = theme;\r\n }\r\n\r\n /**\r\n * Scale the canvas based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n scale(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n var padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n var scaleX = this.canvas.offsetWidth / this.drawingWidth;\r\n var scaleY = this.canvas.offsetHeight / this.drawingHeight;\r\n\r\n var scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n\r\n this.ctx.scale(scale, scale);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.canvas.offsetHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.canvas.offsetWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Resets the transform of the canvas.\r\n */\r\n reset() {\r\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.colors) {\r\n return this.colors[key];\r\n }\r\n\r\n return this.colors['C'];\r\n }\r\n\r\n /**\r\n * Draws a circle to a canvas context.\r\n * @param {Number} x The x coordinate of the circles center.\r\n * @param {Number} y The y coordinate of the circles center.\r\n * @param {Number} radius The radius of the circle\r\n * @param {String} color A hex encoded color.\r\n * @param {Boolean} [fill=true] Whether to fill or stroke the circle.\r\n * @param {Boolean} [debug=false] Draw in debug mode.\r\n * @param {String} [debugText=''] A debug message.\r\n */\r\n drawCircle(x, y, radius, color, fill = true, debug = false, debugText = '') {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.lineWidth = 1.5;\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, radius, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n\r\n if (debug) {\r\n if (fill) {\r\n ctx.fillStyle = '#f00';\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = '#f00';\r\n ctx.stroke();\r\n }\r\n\r\n this.drawDebugText(x, y, debugText);\r\n } else {\r\n if (fill) {\r\n ctx.fillStyle = color;\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = color;\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a line to a canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} [dashed=false] Whether or not the line is dashed.\r\n * @param {Number} [alpha=1.0] The alpha value of the color.\r\n */\r\n drawLine(line, dashed = false, alpha = 1.0) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(4.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n // Draw the \"shadow\"\r\n if (!dashed) {\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness + 1.2;\r\n ctx.strokeStyle = this.themeManager.getColor('BACKGROUND');\r\n ctx.stroke();\r\n ctx.globalCompositeOperation = 'source-over';\r\n ctx.restore();\r\n }\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n\r\n let gradient = this.ctx.createLinearGradient(l.x, l.y, r.x, r.y);\r\n if (line.isDecayPoint) {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(\"DECAY\"));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(\"DECAY\"));\r\n } else {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n }\r\n\r\n if (dashed) {\r\n ctx.setLineDash([1, 1.5]);\r\n ctx.lineWidth = this.opts.bondThickness / 1.5;\r\n }\r\n\r\n if (alpha < 1.0) {\r\n ctx.globalAlpha = alpha;\r\n }\r\n\r\n ctx.strokeStyle = gradient;\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Number} width The wedge width.\r\n */\r\n drawWedge(line, width = 1.0) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(5.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l;\r\n let end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness));\r\n let u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness));\r\n let v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness));\r\n let w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(t.x, t.y);\r\n ctx.lineTo(u.x, u.y);\r\n ctx.lineTo(v.x, v.y);\r\n ctx.lineTo(w.x, w.y);\r\n\r\n let gradient = this.ctx.createRadialGradient(r.x, r.y, this.opts.bondLength, r.x, r.y, 0);\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n let l = line.getLeftVector().clone();\r\n let r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start;\r\n let end;\r\n let sStart;\r\n let sEnd;\r\n\r\n let shortLine = line.clone();\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n\r\n shortLine.shortenRight(1.0);\r\n\r\n sStart = shortLine.getRightVector().clone();\r\n sEnd = shortLine.getLeftVector().clone();\r\n } else {\r\n start = l;\r\n end = r;\r\n\r\n shortLine.shortenLeft(1.0);\r\n\r\n sStart = shortLine.getLeftVector().clone();\r\n sEnd = shortLine.getRightVector().clone();\r\n }\r\n\r\n sStart.x += offsetX;\r\n sStart.y += offsetY;\r\n sEnd.x += offsetX;\r\n sEnd.y += offsetY;\r\n\r\n let dir = Vector2.subtract(end, start).normalize();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n let length = line.getLength();\r\n let step = 1.25 / (length / (this.opts.bondThickness * 3.0));\r\n\r\n let changed = false;\r\n for (var t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length);\r\n let startDash = Vector2.add(start, to);\r\n let width = 1.5 * t;\r\n let dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n if (!changed && t > 0.5) {\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.strokeStyle = this.themeManager.getColor(line.getRightElement()) || this.themeManager.getColor('C');\r\n changed = true;\r\n }\r\n \r\n startDash.subtract(dashOffset);\r\n ctx.moveTo(startDash.x, startDash.y);\r\n startDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n ctx.lineTo(startDash.x, startDash.y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.font = '5px Droid Sans, sans-serif';\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'top';\r\n ctx.fillStyle = '#ff0000';\r\n ctx.fillText(text, x + this.offsetX, y + this.offsetY);\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a ball to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, this.opts.bondLength / 4.5, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a point to the canvas.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, 1.5, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, 0.75, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'alphabetic';\r\n\r\n // Charge\r\n let chargeText = '';\r\n let chargeWidth = 0;\r\n\r\n if (charge) {\r\n chargeText = getChargeText(charge);\r\n\r\n ctx.font = this.fontSmall;\r\n chargeWidth = ctx.measureText(chargeText).width;\r\n }\r\n\r\n let isotopeText = '0';\r\n let isotopeWidth = 0;\r\n\r\n if (isotope > 0) {\r\n isotopeText = isotope.toString();\r\n ctx.font = this.fontSmall;\r\n isotopeWidth = ctx.measureText(isotopeText).width;\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') && \r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = { '0O': { element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: '' } };\r\n charge = 0;\r\n }\r\n\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillStyle = this.themeManager.getColor('BACKGROUND');\r\n\r\n let dim = ctx.measureText(elementName);\r\n\r\n dim.totalWidth = dim.width + chargeWidth;\r\n dim.height = parseInt(this.fontLarge, 10);\r\n\r\n let r = (dim.width > this.opts.fontSizeLarge) ? dim.width : this.opts.fontSizeLarge;\r\n r /= 1.5;\r\n\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, r, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n let cursorPos = -dim.width / 2.0;\r\n let cursorPosLeft = -dim.width / 2.0;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fillText(elementName, x + offsetX + cursorPos, y + this.opts.halfFontSizeLarge + offsetY);\r\n cursorPos += dim.width;\r\n\r\n if (charge) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(chargeText, x + offsetX + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += chargeWidth;\r\n }\r\n\r\n if (isotope > 0) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(isotopeText, x + offsetX + cursorPosLeft - isotopeWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPosLeft -= isotopeWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hydrogenWidth = 0;\r\n let hydrogenCountWidth = 0;\r\n\r\n if (hydrogens === 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n cursorPosLeft -= hydrogenWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.fillText('H', hx, hy);\r\n\r\n cursorPos += hydrogenWidth;\r\n } else if (hydrogens > 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n ctx.font = this.fontSmall;\r\n hydrogenCountWidth = ctx.measureText(hydrogens).width;\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillText('H', hx, hy);\r\n\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogens, hx + this.halfHydrogenWidth + hydrogenCountWidth, hy + this.opts.fifthFontSizeSmall);\r\n\r\n cursorPos += hydrogenWidth + this.halfHydrogenWidth + hydrogenCountWidth;\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let openParenthesisWidth = 0;\r\n let closeParenthesisWidth = 0;\r\n\r\n let element = attachedPseudoElement[key].element;\r\n let elementCount = attachedPseudoElement[key].count;\r\n let hydrogenCount = attachedPseudoElement[key].hydrogenCount;\r\n let elementCharge = attachedPseudoElement[key].charge;\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n openParenthesisWidth = ctx.measureText('(').width;\r\n closeParenthesisWidth = ctx.measureText(')').width;\r\n }\r\n\r\n let elementWidth = ctx.measureText(element).width;\r\n let elementCountWidth = 0;\r\n\r\n let elementChargeText = '';\r\n let elementChargeWidth = 0;\r\n\r\n hydrogenWidth = 0;\r\n\r\n if (hydrogenCount > 0) {\r\n hydrogenWidth = this.hydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n elementCountWidth = ctx.measureText(elementCount).width;\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n elementChargeText = getChargeText(elementCharge);\r\n elementChargeWidth = ctx.measureText(elementChargeText).width;\r\n }\r\n\r\n hydrogenCountWidth = 0;\r\n\r\n if (hydrogenCount > 1) {\r\n hydrogenCountWidth = ctx.measureText(hydrogenCount).width;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(element);\r\n\r\n if (elementCount > 0) {\r\n cursorPosLeft -= elementCountWidth;\r\n }\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= closeParenthesisWidth;\r\n ctx.fillText(')', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText('(', hx + cursorPos, hy);\r\n cursorPos += openParenthesisWidth;\r\n }\r\n }\r\n\r\n if (direction === 'left') {\r\n cursorPosLeft -= elementWidth;\r\n ctx.fillText(element, hx + cursorPosLeft, hy)\r\n } else {\r\n ctx.fillText(element, hx + cursorPos, hy);\r\n cursorPos += elementWidth;\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n ctx.fillText('H', hx + cursorPosLeft, hy);\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPosLeft + hydrogenWidth, hy + this.opts.fifthFontSizeSmall);\r\n }\r\n } else {\r\n ctx.fillText('H', hx + cursorPos, hy);\r\n cursorPos += hydrogenWidth;\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += hydrogenCountWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= openParenthesisWidth;\r\n ctx.fillText('(', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText(')', hx + cursorPos, hy);\r\n cursorPos += closeParenthesisWidth;\r\n }\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementCount, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, hy + this.opts.fifthFontSizeSmall);\r\n } else {\r\n ctx.fillText(elementCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += elementCountWidth;\r\n }\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementChargeText, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n } else {\r\n ctx.fillText(elementChargeText, hx + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += elementChargeWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\n getChargeText(charge) {\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Draws a dubug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n this.drawCircle(x, y, 2, color, true, true, debugText);\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Clear the canvas.\r\n *\r\n */\r\n clear() {\r\n this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = CanvasWrapper;","//@ts-check\r\n\r\nclass DecayPoint {\r\n\r\n /**\r\n * Enum values for Decay points\r\n * ALL use all variants of decay points\r\n * COO -CO-O- type of decay\r\n * CONH -CO-NH- type of decay\r\n * @return {{ALL: number, COO: number, CONH: number}}\r\n */\r\n static get VALUES() {\r\n return { ALL: 0, COO: 1, CONH: 2 };\r\n }\r\n}\r\n\r\nmodule.exports = DecayPoint;\r\n","//@ts-check\r\n\r\nclass DecayState {\r\n\r\n static get VALUES() {\r\n return { NO: 0, STANDARD: 1, SOURCE: 2, STANDARD_AND_SOURCE: 3};\r\n }\r\n}\r\n\r\nmodule.exports = DecayState;\r\n","\r\nclass Direction {\r\n\r\n static get VALUES() {\r\n return { N: 0, POLYKETIDE: 1, C: 2 };\r\n }\r\n\r\n static getProperValue(isPolyketide, vertexElement, vertexId, firstVertexId) {\r\n if (isPolyketide) {\r\n return this.VALUES.POLYKETIDE;\r\n }\r\n if (vertexElement === \"C\" && vertexId !== firstVertexId) {\r\n return this.VALUES.C;\r\n }\r\n return this.VALUES.N;\r\n }\r\n\r\n}\r\n\r\nmodule.exports= Direction;\r\n","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Atom = require('./Atom');\r\nconst Ring = require('./Ring');\r\nconst RingConnection = require('./RingConnection');\r\nconst CanvasWrapper = require('./CanvasWrapper');\r\nconst Graph = require('./Graph');\r\nconst SSSR = require('./SSSR');\r\nconst DecayState = require('./DecayState');\r\nconst ThemeManager = require('./ThemeManager');\r\n\r\n/**\r\n * The main class of the application representing the smiles drawer\r\n *\r\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\r\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\r\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} totalOverlapScore The current internal total overlap score.\r\n * @property {Object} defaultOptions The default options.\r\n * @property {Object} opts The merged options.\r\n * @property {Object} theme The current theme.\r\n */\r\nclass Drawer {\r\n /**\r\n * The constructor for the class SmilesDrawer.\r\n *\r\n * @param {Object} options An object containing custom values for different options. It is merged with the default options.\r\n */\r\n constructor(options) {\r\n this.graph = null;\r\n this.doubleBondConfigCount = 0;\r\n this.doubleBondConfig = null;\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n this.canvasWrapper = null;\r\n this.totalOverlapScore = 0;\r\n\r\n this.defaultOptions = {\r\n width: 500,\r\n height: 500,\r\n offsetX: 0, /* offsetX offset of canvas in page X. Typically canvas.offsetLeft */\r\n offsetY: 0, /* offsetY offset of canvas in page Y. Typically canvas.offsetTop */\r\n bondThickness: 0.6,\r\n bondLength: 15,\r\n shortBondLength: 0.85,\r\n bondSpacing: 0.18 * 15,\r\n atomVisualization: 'default',\r\n isomeric: true,\r\n debug: false,\r\n terminalCarbons: false,\r\n explicitHydrogens: false,\r\n overlapSensitivity: 0.42,\r\n overlapResolutionIterations: 1,\r\n compactDrawing: true,\r\n fontSizeLarge: 5,\r\n fontSizeSmall: 3,\r\n padding: 20.0,\r\n experimentalSSSR: false,\r\n kkThreshold: 0.1,\r\n kkInnerThreshold: 0.1,\r\n kkMaxIteration: 20000,\r\n kkMaxInnerIteration: 50,\r\n kkMaxEnergy: 1e9,\r\n drawDecayPoints: DecayState.VALUES.NO,\r\n decaySource: [],\r\n mouseTolerance: 3,\r\n themes: {\r\n dark: {\r\n C: '#fff',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#fff',\r\n BACKGROUND: '#141414',\r\n DECAY: '#027c21'\r\n },\r\n light: {\r\n C: '#222',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#222',\r\n BACKGROUND: '#fff',\r\n DECAY: '#027c21'\r\n }\r\n }\r\n };\r\n\r\n this.opts = this.extend(true, this.defaultOptions, options);\r\n this.opts.halfBondSpacing = this.opts.bondSpacing / 2.0;\r\n this.opts.bondLengthSq = this.opts.bondLength * this.opts.bondLength;\r\n this.opts.halfFontSizeLarge = this.opts.fontSizeLarge / 2.0;\r\n this.opts.quarterFontSizeLarge = this.opts.fontSizeLarge / 4.0;\r\n this.opts.fifthFontSizeSmall = this.opts.fontSizeSmall / 5.0;\r\n\r\n // Set the default theme.\r\n this.theme = this.opts.themes.dark;\r\n\r\n this.drawDecayPoints = this.opts.drawDecayPoints;\r\n }\r\n\r\n /**\r\n * A helper method to extend the default options with user supplied ones.\r\n */\r\n extend() {\r\n let that = this;\r\n let extended = {};\r\n let deep = false;\r\n let i = 0;\r\n let length = arguments.length;\r\n\r\n if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {\r\n deep = arguments[0];\r\n i++;\r\n }\r\n\r\n let merge = function (obj) {\r\n for (var prop in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, prop)) {\r\n if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\r\n extended[prop] = that.extend(true, extended[prop], obj[prop]);\r\n } else {\r\n extended[prop] = obj[prop];\r\n }\r\n }\r\n }\r\n };\r\n\r\n for (; i < length; i++) {\r\n let obj = arguments[i];\r\n merge(obj);\r\n }\r\n\r\n return extended;\r\n }\r\n\r\n /**\r\n * Is setup to draw decay points?\r\n * when boolean this.drawDecayPoint is true then return isDecay\r\n * @param isDecay bool - edge.isDecay\r\n * @returns {Boolean}\r\n */\r\n isDrawDecayPoint(isDecay) {\r\n return this.drawDecayPoints !== DecayState.VALUES.NO && isDecay;\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to a canvas element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n this.initDraw(data, themeName, infoOnly);\r\n\r\n if (!this.infoOnly) {\r\n this.themeManager = new ThemeManager(this.opts.themes, themeName);\r\n this.canvasWrapper = new CanvasWrapper(target, this.themeManager, this.opts);\r\n }\r\n\r\n if (!infoOnly) {\r\n this.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n\r\n if (this.opts.debug) {\r\n console.log(this.graph);\r\n console.log(this.rings);\r\n console.log(this.ringConnections);\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n if (this.canvasWrapper) {\r\n this.canvasWrapper.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of rings this edge is a part of.\r\n *\r\n * @param {Number} edgeId The id of an edge.\r\n * @returns {Number} The number of rings the provided edge is part of.\r\n */\r\n edgeRingCount(edgeId) {\r\n let edge = this.graph.edges[edgeId];\r\n let a = this.graph.vertices[edge.sourceId];\r\n let b = this.graph.vertices[edge.targetId];\r\n\r\n return Math.min(a.value.rings.length, b.value.rings.length);\r\n }\r\n\r\n /**\r\n * Returns an array containing the bridged rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all bridged rings associated with this molecule.\r\n */\r\n getBridgedRings() {\r\n let bridgedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n bridgedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return bridgedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all fused rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all fused rings associated with this molecule.\r\n */\r\n getFusedRings() {\r\n let fusedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isFused) {\r\n fusedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return fusedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all spiros associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all spiros associated with this molecule.\r\n */\r\n getSpiros() {\r\n let spiros = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isSpiro) {\r\n spiros.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return spiros;\r\n }\r\n\r\n /**\r\n * Returns a string containing a semicolon and new-line separated list of ring properties: Id; Members Count; Neighbours Count; IsSpiro; IsFused; IsBridged; Ring Count (subrings of bridged rings)\r\n *\r\n * @returns {String} A string as described in the method description.\r\n */\r\n printRingInfo() {\r\n let result = '';\r\n for (let i = 0; i < this.rings.length; i++) {\r\n const ring = this.rings[i];\r\n\r\n result += ring.id + ';';\r\n result += ring.members.length + ';';\r\n result += ring.neighbours.length + ';';\r\n result += ring.isSpiro ? 'true;' : 'false;';\r\n result += ring.isFused ? 'true;' : 'false;';\r\n result += ring.isBridged ? 'true;' : 'false;';\r\n result += ring.rings.length + ';';\r\n result += '\\n';\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Rotates the drawing to make the widest dimension horizontal.\r\n */\r\n rotateDrawing() {\r\n // Rotate the vertices to make the molecule align horizontally\r\n // Find the longest distance\r\n let a = 0;\r\n let b = 0;\r\n let maxDist = 0;\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertexA = this.graph.vertices[i];\r\n\r\n if (!vertexA.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n for (let j = i + 1; j < this.graph.vertices.length; j++) {\r\n let vertexB = this.graph.vertices[j];\r\n\r\n if (!vertexB.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = vertexA.position.distanceSq(vertexB.position);\r\n\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n a = i;\r\n b = j;\r\n }\r\n }\r\n }\r\n\r\n let angle = -Vector2.subtract(this.graph.vertices[a].position, this.graph.vertices[b].position).angle();\r\n\r\n if (!isNaN(angle)) {\r\n // Round to 30 degrees\r\n let remainder = angle % 0.523599;\r\n\r\n // Round either up or down in 30 degree steps\r\n if (remainder < 0.2617995) {\r\n angle = angle - remainder;\r\n } else {\r\n angle += 0.523599 - remainder;\r\n }\r\n\r\n // Finally, rotate everything\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (i === b) {\r\n continue;\r\n }\r\n\r\n this.graph.vertices[i].position.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.rings[i].center.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.totalOverlapScore;\r\n }\r\n\r\n /**\r\n * Returns the ring count of the current molecule.\r\n *\r\n * @returns {Number} The ring count.\r\n */\r\n getRingCount() {\r\n return this.rings.length;\r\n }\r\n\r\n /**\r\n * Checks whether or not the current molecule a bridged ring.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not the current molecule a bridged ring.\r\n */\r\n hasBridgedRing() {\r\n return this.bridgedRing;\r\n }\r\n\r\n /**\r\n * Returns the number of heavy atoms (non-hydrogen) in the current molecule.\r\n *\r\n * @returns {Number} The heavy atom count.\r\n */\r\n getHeavyAtomCount() {\r\n let hac = 0;\r\n\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.element !== 'H') {\r\n hac++;\r\n }\r\n }\r\n\r\n return hac;\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n let molecularFormula = '';\r\n let counts = new Map();\r\n\r\n // Initialize element count\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n let atom = this.graph.vertices[i].value;\r\n\r\n if (counts.has(atom.element)) {\r\n counts.set(atom.element, counts.get(atom.element) + 1);\r\n } else {\r\n counts.set(atom.element, 1);\r\n }\r\n\r\n // Hydrogens attached to a chiral center were added as vertices,\r\n // those in non chiral brackets are added here\r\n if (atom.bracket && !atom.bracket.chirality) {\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + atom.bracket.hcount);\r\n } else {\r\n counts.set('H', atom.bracket.hcount);\r\n }\r\n }\r\n\r\n // Add the implicit hydrogens according to valency, exclude\r\n // bracket atoms as they were handled and always have the number\r\n // of hydrogens specified explicitly\r\n if (!atom.bracket) {\r\n let nHydrogens = Atom.maxBonds[atom.element] - atom.bondCount;\r\n\r\n if (atom.isPartOfAromaticRing) {\r\n nHydrogens--;\r\n }\r\n\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + nHydrogens);\r\n } else {\r\n counts.set('H', nHydrogens);\r\n }\r\n }\r\n }\r\n\r\n if (counts.has('C')) {\r\n let count = counts.get('C');\r\n molecularFormula += 'C' + (count > 1 ? count : '');\r\n counts.delete('C');\r\n }\r\n\r\n if (counts.has('H')) {\r\n let count = counts.get('H');\r\n molecularFormula += 'H' + (count > 1 ? count : '');\r\n counts.delete('H');\r\n }\r\n\r\n let elements = Object.keys(Atom.atomicNumbers).sort();\r\n\r\n elements.map(e => {\r\n if (counts.has(e)) {\r\n let count = counts.get(e);\r\n molecularFormula += e + (count > 1 ? count : '');\r\n }\r\n });\r\n\r\n return molecularFormula;\r\n }\r\n\r\n /**\r\n * Returns the type of the ringbond (e.g. '=' for a double bond). The ringbond represents the break in a ring introduced when creating the MST. If the two vertices supplied as arguments are not part of a common ringbond, the method returns null.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(String|null)} Returns the ringbond type or null, if the two supplied vertices are not connected by a ringbond.\r\n */\r\n getRingbondType(vertexA, vertexB) {\r\n // Checks whether the two vertices are the ones connecting the ring\r\n // and what the bond type should be.\r\n if (vertexA.value.getRingbondCount() < 1 || vertexB.value.getRingbondCount() < 1) {\r\n return null;\r\n }\r\n\r\n for (var i = 0; i < vertexA.value.ringbonds.length; i++) {\r\n for (var j = 0; j < vertexB.value.ringbonds.length; j++) {\r\n // if(i != j) continue;\r\n if (vertexA.value.ringbonds[i].id === vertexB.value.ringbonds[j].id) {\r\n // If the bonds are equal, it doesn't matter which bond is returned.\r\n // if they are not equal, return the one that is not the default (\"-\")\r\n if (vertexA.value.ringbonds[i].bondType === '-') {\r\n return vertexB.value.ringbonds[j].bond;\r\n } else {\r\n return vertexA.value.ringbonds[i].bond;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n initDraw(data, themeName, infoOnly) {\r\n this.data = data;\r\n this.infoOnly = infoOnly;\r\n\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n\r\n this.graph = new Graph(data, this.opts.isomeric, this.opts);\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n this.bridgedRing = false;\r\n\r\n // Reset those, in case the previous drawn SMILES had a dangling \\ or /\r\n this.doubleBondConfigCount = null;\r\n this.doubleBondConfig = null;\r\n\r\n this.initRings();\r\n this.initHydrogens();\r\n this.graph.findDecayPoints();\r\n }\r\n\r\n processGraph() {\r\n this.position();\r\n\r\n // Restore the ring information (removes bridged rings and replaces them with the original, multiple, rings)\r\n this.restoreRingInformation();\r\n\r\n // Atoms bonded to the same ring atom\r\n this.resolvePrimaryOverlaps();\r\n\r\n let overlapScore = this.getOverlapScore();\r\n\r\n this.totalOverlapScore = this.getOverlapScore().total;\r\n\r\n for (var o = 0; o < this.opts.overlapResolutionIterations; o++) {\r\n for (var i = 0; i < this.graph.edges.length; i++) {\r\n let edge = this.graph.edges[i];\r\n if (this.isEdgeRotatable(edge)) {\r\n let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\r\n let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\r\n\r\n // Only rotate the shorter subtree\r\n let a = edge.targetId;\r\n let b = edge.sourceId;\r\n\r\n if (subTreeDepthA > subTreeDepthB) {\r\n a = edge.sourceId;\r\n b = edge.targetId;\r\n }\r\n\r\n let subTreeOverlap = this.getSubtreeOverlapScore(b, a, overlapScore.vertexScores);\r\n if (subTreeOverlap.value > this.opts.overlapSensitivity) {\r\n let vertexA = this.graph.vertices[a];\r\n let vertexB = this.graph.vertices[b];\r\n let neighboursB = vertexB.getNeighbours(a);\r\n\r\n if (neighboursB.length === 1) {\r\n let neighbour = this.graph.vertices[neighboursB[0]];\r\n let angle = neighbour.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbour.id, vertexB.id, angle, vertexB.position);\r\n // If the new overlap is bigger, undo change\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbour.id, vertexB.id, -angle, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n } else if (neighboursB.length === 2) {\r\n // Switch places / sides\r\n // If vertex a is in a ring, do nothing\r\n if (vertexB.value.rings.length !== 0 && vertexA.value.rings.length !== 0) {\r\n continue;\r\n }\r\n\r\n let neighbourA = this.graph.vertices[neighboursB[0]];\r\n let neighbourB = this.graph.vertices[neighboursB[1]];\r\n\r\n if (neighbourA.value.rings.length === 1 && neighbourB.value.rings.length === 1) {\r\n // Both neighbours in same ring. TODO: does this create problems with wedges? (up = down and vice versa?)\r\n if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\r\n continue;\r\n }\r\n // TODO: Rotate circle\r\n } else if (neighbourA.value.rings.length !== 0 || neighbourB.value.rings.length !== 0) {\r\n continue;\r\n } else {\r\n let angleA = neighbourA.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n let angleB = neighbourB.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbourA.id, vertexB.id, angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, angleB, vertexB.position);\r\n\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbourA.id, vertexB.id, -angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, -angleB, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n }\r\n }\r\n\r\n overlapScore = this.getOverlapScore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.resolveSecondaryOverlaps(overlapScore.scores);\r\n\r\n if (this.opts.isomeric) {\r\n this.annotateStereochemistry();\r\n }\r\n\r\n // Initialize pseudo elements or shortcuts\r\n if (this.opts.compactDrawing && this.opts.atomVisualization === 'default') {\r\n this.initPseudoElements();\r\n }\r\n\r\n this.rotateDrawing();\r\n }\r\n\r\n /**\r\n * Initializes rings and ringbonds for the current molecule.\r\n */\r\n initRings() {\r\n let openBonds = new Map();\r\n\r\n // Close the open ring bonds (spanning tree -> graph)\r\n for (let i = this.graph.vertices.length - 1; i >= 0; i--) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.ringbonds.length === 0) {\r\n continue;\r\n }\r\n\r\n for (let j = 0; j < vertex.value.ringbonds.length; j++) {\r\n let ringbondId = vertex.value.ringbonds[j].id;\r\n let ringbondBond = vertex.value.ringbonds[j].bond;\r\n\r\n // If the other ringbond id has not been discovered,\r\n // add it to the open bonds map and continue.\r\n // if the other ringbond id has already been discovered,\r\n // create a bond between the two atoms.\r\n if (!openBonds.has(ringbondId)) {\r\n openBonds.set(ringbondId, [vertex.id, ringbondBond]);\r\n } else {\r\n let sourceVertexId = vertex.id;\r\n let targetVertexId = openBonds.get(ringbondId)[0];\r\n let targetRingbondBond = openBonds.get(ringbondId)[1];\r\n let edge = new Edge(sourceVertexId, targetVertexId, 1);\r\n edge.setBondType(targetRingbondBond || ringbondBond || '-');\r\n let edgeId = this.graph.addEdge(edge);\r\n let targetVertex = this.graph.vertices[targetVertexId];\r\n\r\n vertex.addRingbondChild(targetVertexId, j);\r\n vertex.value.addNeighbouringElement(targetVertex.value.element);\r\n targetVertex.addRingbondChild(sourceVertexId, j);\r\n targetVertex.value.addNeighbouringElement(vertex.value.element);\r\n vertex.edges.push(edgeId);\r\n targetVertex.edges.push(edgeId);\r\n\r\n openBonds.delete(ringbondId);\r\n }\r\n }\r\n }\r\n\r\n // Get the rings in the graph (the SSSR)\r\n let rings = SSSR.getRings(this.graph, this.opts.experimentalSSSR);\r\n\r\n if (rings === null) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < rings.length; i++) {\r\n let ringVertices = [...rings[i]];\r\n let ringId = this.addRing(new Ring(ringVertices));\r\n\r\n // Add the ring to the atoms\r\n for (let j = 0; j < ringVertices.length; j++) {\r\n this.graph.vertices[ringVertices[j]].value.rings.push(ringId);\r\n }\r\n }\r\n\r\n // Find connection between rings\r\n // Check for common vertices and create ring connections. This is a bit\r\n // ugly, but the ringcount is always fairly low (< 100)\r\n for (let i = 0; i < this.rings.length - 1; i++) {\r\n for (let j = i + 1; j < this.rings.length; j++) {\r\n let a = this.rings[i];\r\n let b = this.rings[j];\r\n let ringConnection = new RingConnection(a, b);\r\n\r\n // If there are no vertices in the ring connection, then there\r\n // is no ring connection\r\n if (ringConnection.vertices.size > 0) {\r\n this.addRingConnection(ringConnection);\r\n }\r\n }\r\n }\r\n\r\n // Add neighbours to the rings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n ring.neighbours = RingConnection.getNeighbours(this.ringConnections, ring.id);\r\n }\r\n\r\n // Anchor the ring to one of it's members, so that the ring center will always\r\n // be tied to a single vertex when doing repositionings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n this.graph.vertices[ring.members[0]].value.addAnchoredRing(ring.id);\r\n }\r\n\r\n // Backup the ring information to restore after placing the bridged ring.\r\n // This is needed in order to identify aromatic rings and stuff like this in\r\n // rings that are member of the superring.\r\n this.backupRingInformation();\r\n\r\n\r\n // Replace rings contained by a larger bridged ring with a bridged ring\r\n while (this.rings.length > 0) {\r\n let id = -1;\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isPartOfBridgedRing(ring.id) && !ring.isBridged) {\r\n id = ring.id;\r\n }\r\n }\r\n\r\n if (id === -1) {\r\n break;\r\n }\r\n\r\n let ring = this.getRing(id);\r\n\r\n let involvedRings = this.getBridgedRingRings(ring.id);\r\n\r\n this.bridgedRing = true;\r\n this.createBridgedRing(involvedRings, ring.members[0]);\r\n\r\n // Remove the rings\r\n for (let i = 0; i < involvedRings.length; i++) {\r\n this.removeRing(involvedRings[i]);\r\n }\r\n }\r\n }\r\n\r\n initHydrogens() {\r\n // Do not draw hydrogens except when they are connected to a stereocenter connected to two or more rings.\r\n if (!this.opts.explicitHydrogens) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.element !== 'H') {\r\n continue;\r\n }\r\n\r\n // Hydrogens should have only one neighbour, so just take the first\r\n // Also set hasHydrogen true on connected atom\r\n let neighbour = this.graph.vertices[vertex.neighbours[0]];\r\n neighbour.value.hasHydrogen = true;\r\n\r\n if (!neighbour.value.isStereoCenter || neighbour.value.rings.length < 2 && !neighbour.value.bridgedRing ||\r\n neighbour.value.bridgedRing && neighbour.value.originalRings.length < 2) {\r\n vertex.value.isDrawn = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns all rings connected by bridged bonds starting from the ring with the supplied ring id.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array containing all ring ids of rings part of a bridged ring system.\r\n */\r\n getBridgedRingRings(ringId) {\r\n let involvedRings = Array();\r\n let that = this;\r\n\r\n let recurse = function (r) {\r\n let ring = that.getRing(r);\r\n\r\n involvedRings.push(r);\r\n\r\n for (let i = 0; i < ring.neighbours.length; i++) {\r\n let n = ring.neighbours[i];\r\n\r\n if (involvedRings.indexOf(n) === -1 &&\r\n n !== r &&\r\n RingConnection.isBridge(that.ringConnections, that.graph.vertices, r, n)) {\r\n recurse(n);\r\n }\r\n }\r\n };\r\n\r\n recurse(ringId);\r\n\r\n return ArrayHelper.unique(involvedRings);\r\n }\r\n\r\n /**\r\n * Checks whether or not a ring is part of a bridged ring.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not the supplied ring (by id) is part of a bridged ring system.\r\n */\r\n isPartOfBridgedRing(ringId) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].containsRing(ringId) &&\r\n this.ringConnections[i].isBridge(this.graph.vertices)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Creates a bridged ring.\r\n *\r\n * @param {Number[]} ringIds An array of ids of rings involved in the bridged ring.\r\n * @param {Number} sourceVertexId The vertex id to start the bridged ring discovery from.\r\n * @returns {Ring} The bridged ring.\r\n */\r\n createBridgedRing(ringIds, sourceVertexId) {\r\n let ringMembers = new Set();\r\n let vertices = new Set();\r\n let neighbours = new Set();\r\n\r\n for (let i = 0; i < ringIds.length; i++) {\r\n let ring = this.getRing(ringIds[i]);\r\n ring.isPartOfBridged = true;\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n vertices.add(ring.members[j]);\r\n }\r\n\r\n for (let j = 0; j < ring.neighbours.length; j++) {\r\n let id = ring.neighbours[j];\r\n\r\n if (ringIds.indexOf(id) === -1) {\r\n neighbours.add(ring.neighbours[j]);\r\n }\r\n }\r\n }\r\n\r\n // A vertex is part of the bridged ring if it only belongs to\r\n // one of the rings (or to another ring\r\n // which is not part of the bridged ring).\r\n let leftovers = new Set();\r\n\r\n for (let id of vertices) {\r\n let vertex = this.graph.vertices[id];\r\n let intersection = ArrayHelper.intersection(ringIds, vertex.value.rings);\r\n\r\n if (vertex.value.rings.length === 1 || intersection.length === 1) {\r\n ringMembers.add(vertex.id);\r\n } else {\r\n leftovers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Vertices can also be part of multiple rings and lay on the bridged ring,\r\n // however, they have to have at least two neighbours that are not part of\r\n // two rings\r\n let insideRing = Array();\r\n for (let id of leftovers) {\r\n let vertex = this.graph.vertices[id];\r\n let onRing = false;\r\n\r\n for (let j = 0; j < vertex.edges.length; j++) {\r\n if (this.edgeRingCount(vertex.edges[j]) === 1) {\r\n onRing = true;\r\n }\r\n }\r\n\r\n if (onRing) {\r\n vertex.value.isBridgeNode = true;\r\n ringMembers.add(vertex.id);\r\n } else {\r\n vertex.value.isBridge = true;\r\n ringMembers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Create the ring\r\n let ring = new Ring([...ringMembers]);\r\n this.addRing(ring);\r\n\r\n ring.isBridged = true;\r\n ring.neighbours = [...neighbours];\r\n for (let i = 0; i < ringIds.length; i++) {\r\n ring.rings.push(this.getRing(ringIds[i]).clone());\r\n }\r\n\r\n for (let i = 0; i < ring.members.length; i++) {\r\n this.graph.vertices[ring.members[i]].value.bridgedRing = ring.id;\r\n }\r\n\r\n // Atoms inside the ring are no longer part of a ring but are now\r\n // associated with the bridged ring\r\n for (let i = 0; i < insideRing.length; i++) {\r\n let vertex = this.graph.vertices[insideRing[i]];\r\n vertex.value.rings = Array();\r\n }\r\n\r\n // Remove former rings from members of the bridged ring and add the bridged ring\r\n for (let id of ringMembers) {\r\n let vertex = this.graph.vertices[id];\r\n vertex.value.rings = ArrayHelper.removeAll(vertex.value.rings, ringIds);\r\n vertex.value.rings.push(ring.id);\r\n }\r\n\r\n // Remove all the ring connections no longer used\r\n for (let i = 0; i < ringIds.length; i++) {\r\n for (let j = i + 1; j < ringIds.length; j++) {\r\n this.removeRingConnectionsBetween(ringIds[i], ringIds[j]);\r\n }\r\n }\r\n\r\n // Update the ring connections and add this ring to the neighbours neighbours\r\n for (let id of neighbours) {\r\n let connections = this.getRingConnections(id, ringIds);\r\n\r\n for (let j = 0; j < connections.length; j++) {\r\n this.getRingConnection(connections[j]).updateOther(ring.id, id);\r\n }\r\n\r\n this.getRing(id).neighbours.push(ring.id);\r\n }\r\n\r\n return ring;\r\n }\r\n\r\n /**\r\n * Checks whether or not two vertices are in the same ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices are in the same ring.\r\n */\r\n areVerticesInSameRing(vertexA, vertexB) {\r\n // This is a little bit lighter (without the array and push) than\r\n // getCommonRings().length > 0\r\n for (let i = 0; i < vertexA.value.rings.length; i++) {\r\n for (let j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] === vertexB.value.rings[j]) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array of ring ids shared by both vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Number[]} An array of ids of rings shared by the two vertices.\r\n */\r\n getCommonRings(vertexA, vertexB) {\r\n let commonRings = Array();\r\n\r\n for (var i = 0; i < vertexA.value.rings.length; i++) {\r\n for (var j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] == vertexB.value.rings[j]) {\r\n commonRings.push(vertexA.value.rings[i]);\r\n }\r\n }\r\n }\r\n\r\n return commonRings;\r\n }\r\n\r\n /**\r\n * Returns the aromatic or largest ring shared by the two vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(Ring|null)} If an aromatic common ring exists, that ring, else the largest (non-aromatic) ring, else null.\r\n */\r\n getLargestOrAromaticCommonRing(vertexA, vertexB) {\r\n let commonRings = this.getCommonRings(vertexA, vertexB);\r\n let maxSize = 0;\r\n let largestCommonRing = null;\r\n\r\n for (let i = 0; i < commonRings.length; i++) {\r\n let ring = this.getRing(commonRings[i]);\r\n let size = ring.getSize();\r\n\r\n if (ring.isBenzeneLike(this.graph.vertices)) {\r\n return ring;\r\n } else if (size > maxSize) {\r\n maxSize = size;\r\n largestCommonRing = ring;\r\n }\r\n }\r\n\r\n return largestCommonRing;\r\n }\r\n\r\n /**\r\n * Returns an array of vertices positioned at a specified location.\r\n *\r\n * @param {Vector2} position The position to search for vertices.\r\n * @param {Number} radius The radius within to search.\r\n * @param {Number} excludeVertexId A vertex id to be excluded from the search results.\r\n * @returns {Number[]} An array containing vertex ids in a given location.\r\n */\r\n getVerticesAt(position, radius, excludeVertexId) {\r\n let locals = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.id === excludeVertexId || !vertex.positioned) {\r\n continue;\r\n }\r\n\r\n let distance = position.distanceSq(vertex.position);\r\n\r\n if (distance <= radius * radius) {\r\n locals.push(vertex.id);\r\n }\r\n }\r\n\r\n return locals;\r\n }\r\n\r\n /**\r\n * Returns the closest vertex (connected as well as unconnected).\r\n *\r\n * @param {Vertex} vertex The vertex of which to find the closest other vertex.\r\n * @returns {Vertex} The closest vertex.\r\n */\r\n getClosestVertex(vertex) {\r\n let minDist = 99999;\r\n let minVertex = null;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i];\r\n\r\n if (v.id === vertex.id) {\r\n continue;\r\n }\r\n\r\n let distSq = vertex.position.distanceSq(v.position);\r\n\r\n if (distSq < minDist) {\r\n minDist = distSq;\r\n minVertex = v;\r\n }\r\n }\r\n\r\n return minVertex;\r\n }\r\n\r\n /**\r\n * Add a ring to this representation of a molecule.\r\n *\r\n * @param {Ring} ring A new ring.\r\n * @returns {Number} The ring id of the new ring.\r\n */\r\n addRing(ring) {\r\n ring.id = this.ringIdCounter++;\r\n this.rings.push(ring);\r\n\r\n return ring.id;\r\n }\r\n\r\n /**\r\n * Removes a ring from the array of rings associated with the current molecule.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n removeRing(ringId) {\r\n this.rings = this.rings.filter(function (item) {\r\n return item.id !== ringId;\r\n });\r\n\r\n // Also remove ring connections involving this ring\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.firstRingId !== ringId && item.secondRingId !== ringId;\r\n });\r\n\r\n // Remove the ring as neighbour of other rings\r\n for (var i = 0; i < this.rings.length; i++) {\r\n let r = this.rings[i];\r\n r.neighbours = r.neighbours.filter(function (item) {\r\n return item !== ringId;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets a ring object from the array of rings associated with the current molecule by its id. The ring id is not equal to the index, since rings can be added and removed when processing bridged rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Ring} A ring associated with the current molecule.\r\n */\r\n getRing(ringId) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].id == ringId) {\r\n return this.rings[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Add a ring connection to this representation of a molecule.\r\n *\r\n * @param {RingConnection} ringConnection A new ringConnection.\r\n * @returns {Number} The ring connection id of the new ring connection.\r\n */\r\n addRingConnection(ringConnection) {\r\n ringConnection.id = this.ringConnectionIdCounter++;\r\n this.ringConnections.push(ringConnection);\r\n\r\n return ringConnection.id;\r\n }\r\n\r\n /**\r\n * Removes a ring connection from the array of rings connections associated with the current molecule.\r\n *\r\n * @param {Number} ringConnectionId A ring connection id.\r\n */\r\n removeRingConnection(ringConnectionId) {\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.id !== ringConnectionId;\r\n });\r\n }\r\n\r\n /**\r\n * Removes all ring connections between two vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n */\r\n removeRingConnectionsBetween(vertexIdA, vertexIdB) {\r\n let toRemove = Array();\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let ringConnection = this.ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === vertexIdA && ringConnection.secondRingId === vertexIdB ||\r\n ringConnection.firstRingId === vertexIdB && ringConnection.secondRingId === vertexIdA) {\r\n toRemove.push(ringConnection.id);\r\n }\r\n }\r\n\r\n for (let i = 0; i < toRemove.length; i++) {\r\n this.removeRingConnection(toRemove[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Get a ring connection with a given id.\r\n *\r\n * @param {Number} id\r\n * @returns {RingConnection} The ring connection with the specified id.\r\n */\r\n getRingConnection(id) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].id == id) {\r\n return this.ringConnections[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the ring connections between a ring and a set of rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @param {Number[]} ringIds An array of ring ids.\r\n * @returns {Number[]} An array of ring connection ids.\r\n */\r\n getRingConnections(ringId, ringIds) {\r\n let ringConnections = Array();\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let rc = this.ringConnections[i];\r\n\r\n for (let j = 0; j < ringIds.length; j++) {\r\n let id = ringIds[j];\r\n\r\n if (rc.firstRingId === ringId && rc.secondRingId === id ||\r\n rc.firstRingId === id && rc.secondRingId === ringId) {\r\n ringConnections.push(rc.id);\r\n }\r\n }\r\n }\r\n\r\n return ringConnections;\r\n }\r\n\r\n /**\r\n * Returns the overlap score of the current molecule based on its positioned vertices. The higher the score, the more overlaps occur in the structure drawing.\r\n *\r\n * @returns {Object} Returns the total overlap score and the overlap score of each vertex sorted by score (higher to lower). Example: { total: 99, scores: [ { id: 0, score: 22 }, ... ] }\r\n */\r\n getOverlapScore() {\r\n let total = 0.0;\r\n let overlapScores = new Float32Array(this.graph.vertices.length);\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n overlapScores[i] = 0;\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let j = this.graph.vertices.length;\r\n while (--j > i) {\r\n let a = this.graph.vertices[i];\r\n let b = this.graph.vertices[j];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = Vector2.subtract(a.position, b.position).lengthSq();\r\n\r\n if (dist < this.opts.bondLengthSq) {\r\n let weighted = (this.opts.bondLength - Math.sqrt(dist)) / this.opts.bondLength;\r\n total += weighted;\r\n overlapScores[i] += weighted;\r\n overlapScores[j] += weighted;\r\n }\r\n }\r\n }\r\n\r\n let sortable = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n sortable.push({\r\n id: i,\r\n score: overlapScores[i]\r\n });\r\n }\r\n\r\n sortable.sort(function (a, b) {\r\n return b.score - a.score;\r\n });\r\n\r\n return {\r\n total: total,\r\n scores: sortable,\r\n vertexScores: overlapScores\r\n };\r\n }\r\n\r\n /**\r\n * When drawing a double bond, choose the side to place the double bond. E.g. a double bond should always been drawn inside a ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @param {Vector2[]} sides An array containing the two normals of the line spanned by the two provided vertices.\r\n * @returns {Object} Returns an object containing the following information: {\r\n totalSideCount: Counts the sides of each vertex in the molecule, is an array [ a, b ],\r\n totalPosition: Same as position, but based on entire molecule,\r\n sideCount: Counts the sides of each neighbour, is an array [ a, b ],\r\n position: which side to position the second bond, is 0 or 1, represents the index in the normal array. This is based on only the neighbours\r\n anCount: the number of neighbours of vertexA,\r\n bnCount: the number of neighbours of vertexB\r\n }\r\n */\r\n chooseSide(vertexA, vertexB, sides) {\r\n // Check which side has more vertices\r\n // Get all the vertices connected to the both ends\r\n let an = vertexA.getNeighbours(vertexB.id);\r\n let bn = vertexB.getNeighbours(vertexA.id);\r\n let anCount = an.length;\r\n let bnCount = bn.length;\r\n\r\n // All vertices connected to the edge vertexA to vertexB\r\n let tn = ArrayHelper.merge(an, bn);\r\n\r\n // Only considering the connected vertices\r\n let sideCount = [0, 0];\r\n\r\n for (let i = 0; i < tn.length; i++) {\r\n let v = this.graph.vertices[tn[i]].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n sideCount[0]++;\r\n } else {\r\n sideCount[1]++;\r\n }\r\n }\r\n\r\n // Considering all vertices in the graph, this is to resolve ties\r\n // from the above side counts\r\n let totalSideCount = [0, 0];\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n totalSideCount[0]++;\r\n } else {\r\n totalSideCount[1]++;\r\n }\r\n }\r\n\r\n return {\r\n totalSideCount: totalSideCount,\r\n totalPosition: totalSideCount[0] > totalSideCount[1] ? 0 : 1,\r\n sideCount: sideCount,\r\n position: sideCount[0] > sideCount[1] ? 0 : 1,\r\n anCount: anCount,\r\n bnCount: bnCount\r\n };\r\n }\r\n\r\n /**\r\n * Sets the center for a ring.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n setRingCenter(ring) {\r\n let ringSize = ring.getSize();\r\n let total = new Vector2(0, 0);\r\n\r\n for (let i = 0; i < ringSize; i++) {\r\n total.add(this.graph.vertices[ring.members[i]].position);\r\n }\r\n\r\n ring.center = total.divide(ringSize);\r\n }\r\n\r\n /**\r\n * Gets the center of a ring contained within a bridged ring and containing a given vertex.\r\n *\r\n * @param {Ring} ring A bridged ring.\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {Vector2} The center of the subring that containing the vertex.\r\n */\r\n getSubringCenter(ring, vertex) {\r\n let rings = vertex.value.originalRings;\r\n let center = ring.center;\r\n let smallest = Number.MAX_VALUE;\r\n\r\n // Always get the smallest ring.\r\n for (let i = 0; i < rings.length; i++) {\r\n for (let j = 0; j < ring.rings.length; j++) {\r\n if (rings[i] === ring.rings[j].id) {\r\n if (ring.rings[j].getSize() < smallest) {\r\n center = ring.rings[j].center;\r\n smallest = ring.rings[j].getSize();\r\n }\r\n }\r\n }\r\n }\r\n\r\n return center;\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let that = this;\r\n let drawn = Array(this.graph.edges.length);\r\n drawn.fill(false);\r\n\r\n this.graph.traverseBF(0, function (vertex) {\r\n let edges = that.graph.getEdges(vertex.id);\r\n for (let i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n that.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isRingAromatic(ring)) {\r\n this.canvasWrapper.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bonds to the canvas.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let that = this;\r\n let edge = this.graph.edges[edgeId];\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n let elementA = vertexA.value.element;\r\n let elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && this.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position;\r\n let b = vertexB.position;\r\n let normals = this.getEdgeNormals(edge);\r\n\r\n // Create a point on each side of the line\r\n let sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || this.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && this.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = this.areVerticesInSameRing(vertexA, vertexB);\r\n let s = this.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = this.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n }\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n this.canvasWrapper.drawLine(line, true);\r\n } else {\r\n this.canvasWrapper.drawLine(line);\r\n }\r\n\r\n // The normal edge\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.center || vertexA.isTerminal() && vertexB.isTerminal()) {\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1) {\r\n // Both lines are the same length here\r\n // Add the spacing to the edges (which are of unit length)\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.sideCount[0] > s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.sideCount[0] < s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] > s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] <= s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n this.canvasWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.wedge === 'down') {\r\n this.canvasWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else {\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n this.canvasWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(this.graph.vertices);\r\n let isTerminal = this.opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (this.opts.atomVisualization === 'allballs') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || this.graph.vertices.length === 1) {\r\n if (this.opts.atomVisualization === 'default') {\r\n this.canvasWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (this.opts.atomVisualization === 'balls') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = this.graph.vertices[vertex.neighbours[0]].position;\r\n let b = this.graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n this.canvasWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n // this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (this.opts.debug) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let center = this.rings[i].center;\r\n this.canvasWrapper.drawDebugPoint(center.x, center.y, 'r: ' + this.rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Position the vertices according to their bonds and properties.\r\n */\r\n position() {\r\n let startVertex = null;\r\n\r\n // Always start drawing at a bridged ring if there is one\r\n // If not, start with a ring\r\n // else, start with 0\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.bridgedRing !== null) {\r\n startVertex = this.graph.vertices[i];\r\n break;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n startVertex = this.graph.vertices[this.rings[i].members[0]];\r\n }\r\n }\r\n\r\n if (this.rings.length > 0 && startVertex === null) {\r\n startVertex = this.graph.vertices[this.rings[0].members[0]];\r\n }\r\n\r\n if (startVertex === null) {\r\n startVertex = this.graph.vertices[0];\r\n }\r\n\r\n this.createNextBond(startVertex, null, 0.0);\r\n }\r\n\r\n /**\r\n * Stores the current information associated with rings.\r\n */\r\n backupRingInformation() {\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings.push(this.rings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n this.originalRingConnections.push(this.ringConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.backupRings();\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recently backed up information associated with rings.\r\n */\r\n restoreRingInformation() {\r\n // Get the subring centers from the bridged rings\r\n let bridgedRings = this.getBridgedRings();\r\n\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n for (let i = 0; i < bridgedRings.length; i++) {\r\n let bridgedRing = bridgedRings[i];\r\n\r\n for (var j = 0; j < bridgedRing.rings.length; j++) {\r\n let ring = bridgedRing.rings[j];\r\n this.originalRings[ring.id].center = ring.center;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings.push(this.originalRings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.originalRingConnections.length; i++) {\r\n this.ringConnections.push(this.originalRingConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.restoreRings();\r\n }\r\n }\r\n\r\n // TODO: This needs some cleaning up\r\n\r\n /**\r\n * Creates a new ring, that is, positiones all the vertices inside a ring.\r\n *\r\n * @param {Ring} ring The ring to position.\r\n * @param {(Vector2|null)} [center=null] The center of the ring to be created.\r\n * @param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.\r\n * @param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.\r\n * @param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.\r\n */\r\n createRing(ring, center = null, startVertex = null, previousVertex = null) {\r\n if (ring.positioned) {\r\n return;\r\n }\r\n\r\n center = center ? center : new Vector2(0, 0);\r\n\r\n let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);\r\n let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let angle = MathHelper.centralAngle(ring.getSize());\r\n\r\n ring.centralAngle = angle;\r\n\r\n let a = startingAngle;\r\n let that = this;\r\n let startVertexId = (startVertex) ? startVertex.id : null;\r\n\r\n if (ring.members.indexOf(startVertexId) === -1) {\r\n if (startVertex) {\r\n startVertex.positioned = false;\r\n }\r\n\r\n startVertexId = ring.members[0];\r\n }\r\n\r\n // If the ring is bridged, then draw the vertices inside the ring\r\n // using a force based approach\r\n if (ring.isBridged) {\r\n this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength,\r\n this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration,\r\n this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);\r\n ring.positioned = true;\r\n\r\n // Update the center of the bridged ring\r\n this.setRingCenter(ring);\r\n center = ring.center;\r\n\r\n // Setting the centers for the subrings\r\n for (let i = 0; i < ring.rings.length; i++) {\r\n this.setRingCenter(ring.rings[i]);\r\n }\r\n } else {\r\n ring.eachMember(this.graph.vertices, function (v) {\r\n let vertex = that.graph.vertices[v];\r\n\r\n if (!vertex.positioned) {\r\n vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);\r\n }\r\n\r\n a += angle;\r\n\r\n if (!ring.isBridged || ring.rings.length < 3) {\r\n vertex.angle = a;\r\n vertex.positioned = true;\r\n }\r\n }, startVertexId, (previousVertex) ? previousVertex.id : null);\r\n }\r\n\r\n ring.positioned = true;\r\n ring.center = center;\r\n\r\n // Draw neighbours in decreasing order of connectivity\r\n for (let i = 0; i < orderedNeighbours.length; i++) {\r\n let neighbour = this.getRing(orderedNeighbours[i].neighbour);\r\n\r\n if (neighbour.positioned) {\r\n continue;\r\n }\r\n\r\n let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);\r\n\r\n if (vertices.length === 2) {\r\n // This ring is a fused ring\r\n ring.isFused = true;\r\n neighbour.isFused = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n let vertexB = this.graph.vertices[vertices[1]];\r\n\r\n // Get middle between vertex A and B\r\n let midpoint = Vector2.midpoint(vertexA.position, vertexB.position);\r\n\r\n // Get the normals to the line between A and B\r\n let normals = Vector2.normals(vertexA.position, vertexB.position);\r\n\r\n // Normalize the normals\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n // Set length from middle of side to center (the apothem)\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n let apothem = MathHelper.apothem(r, neighbour.getSize());\r\n\r\n normals[0].multiplyScalar(apothem).add(midpoint);\r\n normals[1].multiplyScalar(apothem).add(midpoint);\r\n\r\n // Pick the normal which results in a larger distance to the previous center\r\n // Also check whether it's inside another ring\r\n let nextCenter = normals[0];\r\n if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {\r\n nextCenter = normals[1];\r\n }\r\n\r\n // Get the vertex (A or B) which is in clock-wise direction of the other\r\n let posA = Vector2.subtract(vertexA.position, nextCenter);\r\n let posB = Vector2.subtract(vertexB.position, nextCenter);\r\n\r\n if (posA.clockwise(posB) === -1) {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA, vertexB);\r\n }\r\n } else {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexB, vertexA);\r\n }\r\n }\r\n } else if (vertices.length === 1) {\r\n // This ring is a spiro\r\n ring.isSpiro = true;\r\n neighbour.isSpiro = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n\r\n // Get the vector pointing from the shared vertex to the new centpositioner\r\n let nextCenter = Vector2.subtract(center, vertexA.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n // Get the distance from the vertex to the center\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertexA.position);\r\n\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA);\r\n }\r\n }\r\n }\r\n\r\n // Next, draw atoms that are not part of a ring that are directly attached to this ring\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let ringMember = this.graph.vertices[ring.members[i]];\r\n let ringMemberNeighbours = ringMember.neighbours;\r\n\r\n // If there are multiple, the ovlerap will be resolved in the appropriate step\r\n for (let j = 0; j < ringMemberNeighbours.length; j++) {\r\n let v = this.graph.vertices[ringMemberNeighbours[j]];\r\n\r\n if (v.positioned) {\r\n continue;\r\n }\r\n\r\n v.value.isConnectedToRing = true;\r\n this.createNextBond(v, ringMember, 0.0);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Rotate an entire subtree by an angle around a center.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree that is to rotate.\r\n * @param {Number} angle An angle in randians.\r\n * @param {Vector2} center The rotational center.\r\n */\r\n rotateSubtree(vertexId, parentVertexId, angle, center) {\r\n let that = this;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n vertex.position.rotateAround(angle, center);\r\n\r\n for (var i = 0; i < vertex.value.anchoredRings.length; i++) {\r\n let ring = that.rings[vertex.value.anchoredRings[i]];\r\n\r\n if (ring) {\r\n ring.center.rotateAround(angle, center);\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Gets the overlap score of a subtree.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree.\r\n * @param {Number[]} vertexOverlapScores An array containing the vertex overlap scores indexed by vertex id.\r\n * @returns {Object} An object containing the total overlap score and the center of mass of the subtree weighted by overlap score { value: 0.2, center: new Vector2() }.\r\n */\r\n getSubtreeOverlapScore(vertexId, parentVertexId, vertexOverlapScores) {\r\n let that = this;\r\n let score = 0;\r\n let center = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n if (!vertex.value.isDrawn) {\r\n return;\r\n }\r\n\r\n let s = vertexOverlapScores[vertex.id];\r\n if (s > that.opts.overlapSensitivity) {\r\n score += s;\r\n count++;\r\n }\r\n\r\n let position = that.graph.vertices[vertex.id].position.clone();\r\n position.multiplyScalar(s);\r\n center.add(position);\r\n });\r\n\r\n center.divide(score);\r\n\r\n return {\r\n value: score / count,\r\n center: center\r\n };\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass.\r\n *\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMass() {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass in the neighbourhood of a given position.\r\n *\r\n * @param {Vector2} vec The point at which to look for neighbours.\r\n * @param {Number} [r=currentBondLength*2.0] The radius of vertices to include.\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMassInNeigbourhood(vec, r = this.opts.bondLength * 2.0) {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n let rSq = r * r;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned && vec.distanceSq(vertex.position) < rSq) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Resolve primary (exact) overlaps, such as two vertices that are connected to the same ring vertex.\r\n */\r\n resolvePrimaryOverlaps() {\r\n let overlaps = Array();\r\n let done = Array(this.graph.vertices.length);\r\n\r\n // Looking for overlaps created by two bonds coming out of a ring atom, which both point straight\r\n // away from the ring and are thus perfectly overlapping.\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n let vertex = this.graph.vertices[ring.members[j]];\r\n\r\n if (done[vertex.id]) {\r\n continue;\r\n }\r\n\r\n done[vertex.id] = true;\r\n\r\n let nonRingNeighbours = this.getNonRingNeighbours(vertex.id);\r\n\r\n if (nonRingNeighbours.length > 1) {\r\n // Look for rings where there are atoms with two bonds outside the ring (overlaps)\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n } else if (nonRingNeighbours.length === 1 && vertex.value.rings.length === 2) {\r\n // Look for bonds coming out of joined rings to adjust the angle, an example is: C1=CC(=CC=C1)[C@]12SCCN1CC1=CC=CC=C21\r\n // where the angle has to be adjusted to account for fused ring\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (let i = 0; i < overlaps.length; i++) {\r\n let overlap = overlaps[i];\r\n\r\n if (overlap.vertices.length === 2) {\r\n let a = overlap.vertices[0];\r\n let b = overlap.vertices[1];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let angle = (2 * Math.PI - this.getRing(overlap.rings[0]).getAngle()) / 6.0;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -angle, overlap.common.position);\r\n\r\n // Decide which way to rotate the vertices depending on the effect it has on the overlap score\r\n let overlapScore = this.getOverlapScore();\r\n let subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n let subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n let total = subTreeOverlapA.value + subTreeOverlapB.value;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n\r\n overlapScore = this.getOverlapScore();\r\n subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n\r\n if (subTreeOverlapA.value + subTreeOverlapB.value > total) {\r\n this.rotateSubtree(a.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n }\r\n } else if (overlap.vertices.length === 1) {\r\n if (overlap.rings.length === 2) {\r\n // TODO: Implement for more overlap resolution\r\n // console.log(overlap);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resolve secondary overlaps. Those overlaps are due to the structure turning back on itself.\r\n *\r\n * @param {Object[]} scores An array of objects sorted descending by score.\r\n * @param {Number} scores[].id A vertex id.\r\n * @param {Number} scores[].score The overlap score associated with the vertex id.\r\n */\r\n resolveSecondaryOverlaps(scores) {\r\n for (let i = 0; i < scores.length; i++) {\r\n if (scores[i].score > this.opts.overlapSensitivity) {\r\n let vertex = this.graph.vertices[scores[i].id];\r\n\r\n if (vertex.isTerminal()) {\r\n let closest = this.getClosestVertex(vertex);\r\n\r\n if (closest) {\r\n // If one of the vertices is the first one, the previous vertex is not the central vertex but the dummy\r\n // so take the next rather than the previous, which is vertex 1\r\n let closestPosition = null;\r\n\r\n if (closest.isTerminal()) {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.previousPosition\r\n } else {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.position\r\n }\r\n\r\n let vertexPreviousPosition = vertex.id === 0 ? this.graph.vertices[1].position : vertex.previousPosition;\r\n\r\n vertex.position.rotateAwayFrom(closestPosition, vertexPreviousPosition, MathHelper.toRad(20));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the last non-null or 0 angle vertex.\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex} The last vertex with an angle that was not 0 or null.\r\n */\r\n getLastVertexWithAngle(vertexId) {\r\n let angle = 0;\r\n let vertex = null;\r\n\r\n while (!angle && vertexId) {\r\n vertex = this.graph.vertices[vertexId];\r\n angle = vertex.angle;\r\n vertexId = vertex.parentVertexId;\r\n }\r\n\r\n return vertex;\r\n }\r\n\r\n /**\r\n * Positiones the next vertex thus creating a bond.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @param {Vertex} [previousVertex=null] The previous vertex which has been positioned.\r\n * @param {Number} [angle=0.0] The (global) angle of the vertex.\r\n * @param {Boolean} [originShortest=false] Whether the origin is the shortest subtree in the branch.\r\n * @param {Boolean} [skipPositioning=false] Whether or not to skip positioning and just check the neighbours.\r\n */\r\n createNextBond(vertex, previousVertex = null, angle = 0.0, originShortest = false, skipPositioning = false) {\r\n if (vertex.positioned && !skipPositioning) {\r\n return;\r\n }\r\n\r\n // If the double bond config was set on this vertex, do not check later\r\n let doubleBondConfigSet = false;\r\n\r\n // Keeping track of configurations around double bonds\r\n if (previousVertex) {\r\n let edge = this.graph.getEdge(vertex.id, previousVertex.id);\r\n\r\n if ((edge.bondType === '/' || edge.bondType === '\\\\') && ++this.doubleBondConfigCount % 2 === 1) {\r\n if (this.doubleBondConfig === null) {\r\n this.doubleBondConfig = edge.bondType;\r\n doubleBondConfigSet = true;\r\n\r\n // Switch if the bond is a branch bond and previous vertex is the first\r\n // TODO: Why is it different with the first vertex?\r\n if (previousVertex.parentVertexId === null && vertex.value.branchBond) {\r\n if (this.doubleBondConfig === '/') {\r\n this.doubleBondConfig = '\\\\';\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n this.doubleBondConfig = '/';\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If the current node is the member of one ring, then point straight away\r\n // from the center of the ring. However, if the current node is a member of\r\n // two rings, point away from the middle of the centers of the two rings\r\n if (!skipPositioning) {\r\n if (!previousVertex) {\r\n // Add a (dummy) previous position if there is no previous vertex defined\r\n // Since the first vertex is at (0, 0), create a vector at (bondLength, 0)\r\n // and rotate it by 90°\r\n\r\n let dummy = new Vector2(this.opts.bondLength, 0);\r\n dummy.rotate(MathHelper.toRad(-60));\r\n\r\n vertex.previousPosition = dummy;\r\n vertex.setPosition(this.opts.bondLength, 0);\r\n vertex.angle = MathHelper.toRad(-60);\r\n\r\n // Do not position the vertex if it belongs to a bridged ring that is positioned using a layout algorithm.\r\n if (vertex.value.bridgedRing === null) {\r\n vertex.positioned = true;\r\n }\r\n } else if (previousVertex.value.rings.length > 0) {\r\n let neighbours = previousVertex.neighbours;\r\n let joinedVertex = null;\r\n let pos = new Vector2(0.0, 0.0);\r\n\r\n if (previousVertex.value.bridgedRing === null && previousVertex.value.rings.length > 1) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n if (ArrayHelper.containsAll(neighbour.value.rings, previousVertex.value.rings)) {\r\n joinedVertex = neighbour;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (joinedVertex === null) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let v = this.graph.vertices[neighbours[i]];\r\n\r\n if (v.positioned && this.areVerticesInSameRing(v, previousVertex)) {\r\n pos.add(Vector2.subtract(v.position, previousVertex.position));\r\n }\r\n }\r\n\r\n pos.invert().normalize().multiplyScalar(this.opts.bondLength).add(previousVertex.position);\r\n } else {\r\n pos = joinedVertex.position.clone().rotateAround(Math.PI, previousVertex.position);\r\n }\r\n\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.setPositionFromVector(pos);\r\n vertex.positioned = true;\r\n } else {\r\n // If the previous vertex was not part of a ring, draw a bond based\r\n // on the global angle of the previous bond\r\n let v = new Vector2(this.opts.bondLength, 0);\r\n\r\n v.rotate(angle);\r\n v.add(previousVertex.position);\r\n\r\n vertex.setPositionFromVector(v);\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.positioned = true;\r\n }\r\n }\r\n\r\n // Go to next vertex\r\n // If two rings are connected by a bond ...\r\n if (vertex.value.bridgedRing !== null) {\r\n let nextRing = this.getRing(vertex.value.bridgedRing);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.members.length);\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else if (vertex.value.rings.length > 0) {\r\n let nextRing = this.getRing(vertex.value.rings[0]);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else {\r\n // Draw the non-ring vertices connected to this one\r\n let isStereoCenter = vertex.value.isStereoCenter;\r\n let tmpNeighbours = vertex.getNeighbours();\r\n let neighbours = Array();\r\n\r\n // Remove neighbours that are not drawn\r\n for (let i = 0; i < tmpNeighbours.length; i++) {\r\n if (this.graph.vertices[tmpNeighbours[i]].value.isDrawn) {\r\n neighbours.push(tmpNeighbours[i]);\r\n }\r\n }\r\n\r\n // Remove the previous vertex (which has already been drawn)\r\n if (previousVertex) {\r\n neighbours = ArrayHelper.remove(neighbours, previousVertex.id);\r\n }\r\n\r\n let previousAngle = vertex.getAngle();\r\n\r\n if (neighbours.length === 1) {\r\n let nextVertex = this.graph.vertices[neighbours[0]];\r\n\r\n // Make a single chain always cis except when there's a tribble (yes, this is a Star Trek reference) bond\r\n // or if there are successive double bonds. Added a ring check because if there is an aromatic ring the ring bond inside the ring counts as a double bond and leads to =-= being straight.\r\n if ((vertex.value.bondType === '#' || (previousVertex && previousVertex.value.bondType === '#')) ||\r\n vertex.value.bondType === '=' && previousVertex && previousVertex.value.rings.length === 0 &&\r\n previousVertex.value.bondType === '=' && vertex.value.branchBond !== '-') {\r\n vertex.value.drawExplicit = false;\r\n\r\n if (previousVertex) {\r\n let straightEdge1 = this.graph.getEdge(vertex.id, previousVertex.id);\r\n straightEdge1.center = true;\r\n }\r\n\r\n let straightEdge2 = this.graph.getEdge(vertex.id, nextVertex.id);\r\n straightEdge2.center = true;\r\n\r\n if (vertex.value.bondType === '#' || previousVertex && previousVertex.value.bondType === '#') {\r\n nextVertex.angle = 0.0;\r\n }\r\n\r\n nextVertex.drawExplicit = true;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else if (previousVertex && previousVertex.value.rings.length > 0) {\r\n // If coming out of a ring, always draw away from the center of mass\r\n let proposedAngleA = MathHelper.toRad(60);\r\n let proposedAngleB = -proposedAngleA;\r\n\r\n let proposedVectorA = new Vector2(this.opts.bondLength, 0);\r\n let proposedVectorB = new Vector2(this.opts.bondLength, 0);\r\n\r\n proposedVectorA.rotate(proposedAngleA).add(vertex.position);\r\n proposedVectorB.rotate(proposedAngleB).add(vertex.position);\r\n\r\n // let centerOfMass = this.getCurrentCenterOfMassInNeigbourhood(vertex.position, 100);\r\n let centerOfMass = this.getCurrentCenterOfMass();\r\n let distanceA = proposedVectorA.distanceSq(centerOfMass);\r\n let distanceB = proposedVectorB.distanceSq(centerOfMass);\r\n\r\n nextVertex.angle = distanceA < distanceB ? proposedAngleB : proposedAngleA;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else {\r\n let a = vertex.angle;\r\n // Take the min and max if the previous angle was in a 4-neighbourhood (90° angles)\r\n // TODO: If a is null or zero, it should be checked whether or not this one should go cis or trans, that is,\r\n // it should go into the oposite direction of the last non-null or 0 previous vertex / angle.\r\n if (previousVertex && previousVertex.neighbours.length > 3) {\r\n if (a > 0) {\r\n a = Math.min(1.0472, a);\r\n } else if (a < 0) {\r\n a = Math.max(-1.0472, a);\r\n } else {\r\n a = 1.0472;\r\n }\r\n } else if (!a) {\r\n let v = this.getLastVertexWithAngle(vertex.id);\r\n a = v.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n }\r\n\r\n // Handle configuration around double bonds\r\n if (previousVertex && !doubleBondConfigSet) {\r\n let bondType = this.graph.getEdge(vertex.id, nextVertex.id).bondType;\r\n\r\n if (bondType === '/') {\r\n if (this.doubleBondConfig === '/') {\r\n // Nothing to do since it will be trans per default\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n a = -a;\r\n }\r\n this.doubleBondConfig = null;\r\n } else if (bondType === '\\\\') {\r\n if (this.doubleBondConfig === '/') {\r\n a = -a;\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n // Nothing to do since it will be trans per default\r\n }\r\n this.doubleBondConfig = null;\r\n }\r\n }\r\n\r\n if (originShortest) {\r\n nextVertex.angle = a;\r\n } else {\r\n nextVertex.angle = -a;\r\n }\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n }\r\n } else if (neighbours.length === 2) {\r\n // If the previous vertex comes out of a ring, it doesn't have an angle set\r\n let a = vertex.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n\r\n // Check for the longer subtree - always go with cis for the longer subtree\r\n let subTreeDepthA = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let subTreeDepthB = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n\r\n let l = this.graph.vertices[neighbours[0]];\r\n let r = this.graph.vertices[neighbours[1]];\r\n\r\n l.value.subtreeDepth = subTreeDepthA;\r\n r.value.subtreeDepth = subTreeDepthB;\r\n\r\n // Also get the subtree for the previous direction (this is important when\r\n // the previous vertex is the shortest path)\r\n let subTreeDepthC = this.graph.getTreeDepth(previousVertex ? previousVertex.id : null, vertex.id);\r\n if (previousVertex) {\r\n previousVertex.value.subtreeDepth = subTreeDepthC;\r\n }\r\n\r\n let cis = 0;\r\n let trans = 1;\r\n\r\n // Carbons go always cis\r\n if (r.value.element === 'C' && l.value.element !== 'C' && subTreeDepthB > 1 && subTreeDepthA < 5) {\r\n cis = 1;\r\n trans = 0;\r\n } else if (r.value.element !== 'C' && l.value.element === 'C' && subTreeDepthA > 1 && subTreeDepthB < 5) {\r\n cis = 0;\r\n trans = 1;\r\n } else if (subTreeDepthB > subTreeDepthA) {\r\n cis = 1;\r\n trans = 0;\r\n }\r\n\r\n let cisVertex = this.graph.vertices[neighbours[cis]];\r\n let transVertex = this.graph.vertices[neighbours[trans]];\r\n\r\n // If the origin tree is the shortest, make them the main chain\r\n let originShortest = false;\r\n if (subTreeDepthC < subTreeDepthA && subTreeDepthC < subTreeDepthB) {\r\n originShortest = true;\r\n }\r\n\r\n transVertex.angle = a;\r\n cisVertex.angle = -a;\r\n\r\n if (this.doubleBondConfig === '\\\\') {\r\n if (transVertex.value.branchBond === '\\\\') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n } else if (this.doubleBondConfig === '/') {\r\n if (transVertex.value.branchBond === '/') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n }\r\n\r\n this.createNextBond(transVertex, vertex, previousAngle + transVertex.angle, originShortest);\r\n this.createNextBond(cisVertex, vertex, previousAngle + cisVertex.angle, originShortest);\r\n } else if (neighbours.length === 3) {\r\n // The vertex with the longest sub-tree should always go straight\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n\r\n let s = this.graph.vertices[neighbours[0]];\r\n let l = this.graph.vertices[neighbours[1]];\r\n let r = this.graph.vertices[neighbours[2]];\r\n\r\n s.value.subtreeDepth = d1;\r\n l.value.subtreeDepth = d2;\r\n r.value.subtreeDepth = d3;\r\n\r\n if (d2 > d1 && d2 > d3) {\r\n s = this.graph.vertices[neighbours[1]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[2]];\r\n } else if (d3 > d1 && d3 > d2) {\r\n s = this.graph.vertices[neighbours[2]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[1]];\r\n }\r\n\r\n // Create a cross if more than one subtree is of length > 1\r\n // or the vertex is connected to a ring\r\n if (previousVertex &&\r\n previousVertex.value.rings.length < 1 &&\r\n s.value.rings.length < 1 &&\r\n l.value.rings.length < 1 &&\r\n r.value.rings.length < 1 &&\r\n this.graph.getTreeDepth(l.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(r.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(s.id, vertex.id) > 1) {\r\n\r\n s.angle = -vertex.angle;\r\n if (vertex.angle >= 0) {\r\n l.angle = MathHelper.toRad(30);\r\n r.angle = MathHelper.toRad(90);\r\n } else {\r\n l.angle = -MathHelper.toRad(30);\r\n r.angle = -MathHelper.toRad(90);\r\n }\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n } else {\r\n s.angle = 0.0;\r\n l.angle = MathHelper.toRad(90);\r\n r.angle = -MathHelper.toRad(90);\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n }\r\n } else if (neighbours.length === 4) {\r\n // The vertex with the longest sub-tree should always go to the reflected opposide direction\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n let d4 = this.graph.getTreeDepth(neighbours[3], vertex.id);\r\n\r\n let w = this.graph.vertices[neighbours[0]];\r\n let x = this.graph.vertices[neighbours[1]];\r\n let y = this.graph.vertices[neighbours[2]];\r\n let z = this.graph.vertices[neighbours[3]];\r\n\r\n w.value.subtreeDepth = d1;\r\n x.value.subtreeDepth = d2;\r\n y.value.subtreeDepth = d3;\r\n z.value.subtreeDepth = d4;\r\n\r\n if (d2 > d1 && d2 > d3 && d2 > d4) {\r\n w = this.graph.vertices[neighbours[1]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[2]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d3 > d1 && d3 > d2 && d3 > d4) {\r\n w = this.graph.vertices[neighbours[2]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d4 > d1 && d4 > d2 && d4 > d3) {\r\n w = this.graph.vertices[neighbours[3]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[2]];\r\n }\r\n\r\n w.angle = -MathHelper.toRad(36);\r\n x.angle = MathHelper.toRad(36);\r\n y.angle = -MathHelper.toRad(108);\r\n z.angle = MathHelper.toRad(108);\r\n\r\n this.createNextBond(w, vertex, previousAngle + w.angle);\r\n this.createNextBond(x, vertex, previousAngle + x.angle);\r\n this.createNextBond(y, vertex, previousAngle + y.angle);\r\n this.createNextBond(z, vertex, previousAngle + z.angle);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Gets the vetex sharing the edge that is the common bond of two rings.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {(Number|null)} The id of a vertex sharing the edge that is the common bond of two rings with the vertex provided or null, if none.\r\n */\r\n getCommonRingbondNeighbour(vertex) {\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n\r\n if (ArrayHelper.containsAll(neighbour.value.rings, vertex.value.rings)) {\r\n return neighbour;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Check if a vector is inside any ring.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Boolean} A boolean indicating whether or not the point (vector) is inside any of the rings associated with the current molecule.\r\n */\r\n isPointInRing(vec) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (!ring.positioned) {\r\n continue;\r\n }\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let radiusSq = radius * radius;\r\n\r\n if (vec.distanceSq(ring.center) < radiusSq) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is part of a ring.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is part of a ring.\r\n */\r\n isEdgeInRing(edge) {\r\n let source = this.graph.vertices[edge.sourceId];\r\n let target = this.graph.vertices[edge.targetId];\r\n\r\n return this.areVerticesInSameRing(source, target);\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is rotatable.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is rotatable.\r\n */\r\n isEdgeRotatable(edge) {\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n\r\n // Only single bonds are rotatable\r\n if (edge.bondType !== '-') {\r\n return false;\r\n }\r\n\r\n // Do not rotate edges that have a further single bond to each side - do that!\r\n // If the bond is terminal, it doesn't make sense to rotate it\r\n // if (vertexA.getNeighbourCount() + vertexB.getNeighbourCount() < 5) {\r\n // return false;\r\n // }\r\n\r\n if (vertexA.isTerminal() || vertexB.isTerminal()) {\r\n return false;\r\n }\r\n\r\n // Ringbonds are not rotatable\r\n return !(vertexA.value.rings.length > 0 && vertexB.value.rings.length > 0 && this.areVerticesInSameRing(vertexA, vertexB));\r\n }\r\n\r\n /**\r\n * Check whether or not a ring is an implicitly defined aromatic ring (lower case smiles).\r\n *\r\n * @param {Ring} ring A ring.\r\n * @returns {Boolean} A boolean indicating whether or not a ring is implicitly defined as aromatic.\r\n */\r\n isRingAromatic(ring) {\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let vertex = this.graph.vertices[ring.members[i]];\r\n\r\n if (!vertex.value.isPartOfAromaticRing) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the normals of an edge.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Vector2[]} An array containing two vectors, representing the normals.\r\n */\r\n getEdgeNormals(edge) {\r\n let v1 = this.graph.vertices[edge.sourceId].position;\r\n let v2 = this.graph.vertices[edge.targetId].position;\r\n\r\n // Get the normalized normals for the edge\r\n return Vector2.units(v1, v2);\r\n }\r\n\r\n /**\r\n * Returns an array of vertices that are neighbouring a vertix but are not members of a ring (including bridges).\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex[]} An array of vertices.\r\n */\r\n getNonRingNeighbours(vertexId) {\r\n let nrneighbours = Array();\r\n let vertex = this.graph.vertices[vertexId];\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n let nIntersections = ArrayHelper.intersection(vertex.value.rings, neighbour.value.rings).length;\r\n\r\n if (nIntersections === 0 && neighbour.value.isBridge == false) {\r\n nrneighbours.push(neighbour);\r\n }\r\n }\r\n\r\n return nrneighbours;\r\n }\r\n\r\n /**\r\n * Annotaed stereochemistry information for visualization.\r\n */\r\n annotateStereochemistry() {\r\n let maxDepth = 10;\r\n\r\n // For each stereo-center\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (!vertex.value.isStereoCenter) {\r\n continue;\r\n }\r\n\r\n let neighbours = vertex.getNeighbours();\r\n let nNeighbours = neighbours.length;\r\n let priorities = Array(nNeighbours);\r\n\r\n for (let j = 0; j < nNeighbours; j++) {\r\n let visited = new Uint8Array(this.graph.vertices.length);\r\n let priority = Array(Array());\r\n visited[vertex.id] = 1;\r\n\r\n this.visitStereochemistry(neighbours[j], vertex.id, visited, priority, maxDepth, 0);\r\n\r\n // Sort each level according to atomic number\r\n for (let k = 0; k < priority.length; k++) {\r\n priority[k].sort(function (a, b) {\r\n return b - a\r\n });\r\n }\r\n\r\n priorities[j] = [j, priority];\r\n }\r\n\r\n let maxLevels = 0;\r\n let maxEntries = 0;\r\n for (let j = 0; j < priorities.length; j++) {\r\n if (priorities[j][1].length > maxLevels) {\r\n maxLevels = priorities[j][1].length;\r\n }\r\n\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n if (priorities[j][1][k].length > maxEntries) {\r\n maxEntries = priorities[j][1][k].length;\r\n }\r\n }\r\n }\r\n\r\n for (let j = 0; j < priorities.length; j++) {\r\n let diff = maxLevels - priorities[j][1].length;\r\n for (let k = 0; k < diff; k++) {\r\n priorities[j][1].push([]);\r\n }\r\n\r\n // Break ties by the position in the SMILES string as per specification\r\n priorities[j][1].push([neighbours[j]]);\r\n\r\n // Make all same length. Fill with zeroes.\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n let diff = maxEntries - priorities[j][1][k].length;\r\n\r\n for (let l = 0; l < diff; l++) {\r\n priorities[j][1][k].push(0);\r\n }\r\n }\r\n }\r\n\r\n priorities.sort(function (a, b) {\r\n for (let j = 0; j < a[1].length; j++) {\r\n for (let k = 0; k < a[1][j].length; k++) {\r\n if (a[1][j][k] > b[1][j][k]) {\r\n return -1;\r\n } else if (a[1][j][k] < b[1][j][k]) {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n\r\n let order = new Uint8Array(nNeighbours);\r\n for (let j = 0; j < nNeighbours; j++) {\r\n order[j] = priorities[j][0];\r\n vertex.value.priority = j;\r\n }\r\n\r\n // Check the angles between elements 0 and 1, and 0 and 2 to determine whether they are\r\n // drawn cw or ccw\r\n // TODO: OC(Cl)=[C@]=C(C)F currently fails here, however this is, IMHO, not a valid SMILES.\r\n let posA = this.graph.vertices[neighbours[order[0]]].position;\r\n let posB = this.graph.vertices[neighbours[order[1]]].position;\r\n\r\n let cwA = posA.relativeClockwise(posB, vertex.position);\r\n\r\n // If the second priority is clockwise from the first, the ligands are drawn clockwise, since\r\n // The hydrogen can be drawn on either side\r\n let isCw = cwA === -1;\r\n\r\n let rotation = vertex.value.bracket.chirality === '@' ? -1 : 1;\r\n let rs = MathHelper.parityOfPermutation(order) * rotation === 1 ? 'R' : 'S';\r\n\r\n // Flip the hydrogen direction when the drawing doesn't match the chirality.\r\n let wedgeA = 'down';\r\n let wedgeB = 'up';\r\n if (isCw && rs !== 'R' || !isCw && rs !== 'S') {\r\n vertex.value.hydrogenDirection = 'up';\r\n wedgeA = 'up';\r\n wedgeB = 'down';\r\n }\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, neighbours[order[order.length - 1]]).wedge = wedgeA;\r\n }\r\n\r\n // Get the shortest subtree to flip up / down. Ignore lowest priority\r\n // The rules are following:\r\n // 1. Do not draw wedge between two stereocenters\r\n // 2. Heteroatoms\r\n // 3. Draw outside ring\r\n // 4. Shortest subtree\r\n\r\n let wedgeOrder = new Array(neighbours.length - 1);\r\n let showHydrogen = vertex.value.rings.length > 1 && vertex.value.hasHydrogen;\r\n let offset = vertex.value.hasHydrogen ? 1 : 0;\r\n\r\n for (let j = 0; j < order.length - offset; j++) {\r\n wedgeOrder[j] = new Uint32Array(2);\r\n let neighbour = this.graph.vertices[neighbours[order[j]]];\r\n wedgeOrder[j][0] += neighbour.value.isStereoCenter ? 0 : 100000;\r\n // wedgeOrder[j][0] += neighbour.value.rings.length > 0 ? 0 : 10000;\r\n // Only add if in same ring, unlike above\r\n wedgeOrder[j][0] += this.areVerticesInSameRing(neighbour, vertex) ? 0 : 10000;\r\n wedgeOrder[j][0] += neighbour.value.isHeteroAtom() ? 1000 : 0;\r\n wedgeOrder[j][0] -= neighbour.value.subtreeDepth === 0 ? 1000 : 0;\r\n wedgeOrder[j][0] += 1000 - neighbour.value.subtreeDepth;\r\n wedgeOrder[j][1] = neighbours[order[j]];\r\n }\r\n\r\n\r\n wedgeOrder.sort(function (a, b) {\r\n if (a[0] > b[0]) {\r\n return -1;\r\n } else if (a[0] < b[0]) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n\r\n // If all neighbours are in a ring, do not draw wedge, the hydrogen will be drawn.\r\n if (!showHydrogen) {\r\n let wedgeId = wedgeOrder[0][1];\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedgeB;\r\n } else {\r\n let wedge = wedgeB;\r\n\r\n for (let j = order.length - 1; j >= 0; j--) {\r\n if (wedge === wedgeA) {\r\n wedge = wedgeB;\r\n } else {\r\n wedge = wedgeA;\r\n }\r\n if (neighbours[order[j]] === wedgeId) {\r\n break;\r\n }\r\n }\r\n\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedge;\r\n }\r\n }\r\n\r\n vertex.value.chirality = rs;\r\n }\r\n }\r\n\r\n /**\r\n *\r\n *\r\n * @param {Number} vertexId The id of a vertex.\r\n * @param {(Number|null)} previousVertexId The id of the parent vertex of the vertex.\r\n * @param {Uint8Array} visited An array containing the visited flag for all vertices in the graph.\r\n * @param {Array} priority An array of arrays storing the atomic numbers for each level.\r\n * @param {Number} maxDepth The maximum depth.\r\n * @param {Number} depth The current depth.\r\n * @param {Number} parentAtomicNumber\r\n */\r\n visitStereochemistry(vertexId, previousVertexId, visited, priority, maxDepth, depth, parentAtomicNumber = 0) {\r\n visited[vertexId] = 1;\r\n let vertex = this.graph.vertices[vertexId];\r\n let atomicNumber = vertex.value.getAtomicNumber();\r\n\r\n if (priority.length <= depth) {\r\n priority.push(Array());\r\n }\r\n\r\n for (let i = 0; i < this.graph.getEdge(vertexId, previousVertexId).weight; i++) {\r\n priority[depth].push(parentAtomicNumber * 1000 + atomicNumber);\r\n }\r\n\r\n let neighbours = this.graph.vertices[vertexId].neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (visited[neighbours[i]] !== 1 && depth < maxDepth - 1) {\r\n this.visitStereochemistry(neighbours[i], vertexId, visited.slice(), priority, maxDepth, depth + 1, atomicNumber);\r\n }\r\n }\r\n\r\n // Valences are filled with hydrogens and passed to the next level.\r\n if (depth < maxDepth - 1) {\r\n let bonds = 0;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n bonds += this.graph.getEdge(vertexId, neighbours[i]).weight;\r\n }\r\n\r\n for (let i = 0; i < vertex.value.getMaxBonds() - bonds; i++) {\r\n if (priority.length <= depth + 1) {\r\n priority.push(Array());\r\n }\r\n\r\n priority[depth + 1].push(atomicNumber * 1000 + 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Creates pseudo-elements (such as Et, Me, Ac, Bz, ...) at the position of the carbon sets\r\n * the involved atoms not to be displayed.\r\n */\r\n initPseudoElements() {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n // Ignore atoms that have less than 3 neighbours, except if\r\n // the vertex is connected to a ring and has two neighbours\r\n if (vertex.getNeighbourCount() < 3 || vertex.value.rings.length > 0) {\r\n continue;\r\n }\r\n\r\n // TODO: This exceptions should be handled more elegantly (via config file?)\r\n\r\n // Ignore phosphates (especially for triphosphates)\r\n if (vertex.value.element === 'P') {\r\n continue;\r\n }\r\n\r\n // Ignore also guanidine\r\n if (vertex.value.element === 'C' && neighbours.length === 3 &&\r\n neighbours[0].value.element === 'N' && neighbours[1].value.element === 'N' && neighbours[2].value.element === 'N') {\r\n continue;\r\n }\r\n\r\n // Continue if there are less than two heteroatoms\r\n // or if a neighbour has more than 1 neighbour\r\n let heteroAtomCount = 0;\r\n let ctn = 0;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n let neighbouringElement = neighbour.value.element;\r\n let neighbourCount = neighbour.getNeighbourCount();\r\n\r\n if (neighbouringElement !== 'C' && neighbouringElement !== 'H' &&\r\n neighbourCount === 1) {\r\n heteroAtomCount++;\r\n }\r\n\r\n if (neighbourCount > 1) {\r\n ctn++;\r\n }\r\n }\r\n\r\n if (ctn > 1 || heteroAtomCount < 2) {\r\n continue;\r\n }\r\n\r\n // Get the previous atom (the one which is not terminal)\r\n let previous = null;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n previous = neighbour;\r\n }\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n continue;\r\n }\r\n\r\n neighbour.value.isDrawn = false;\r\n\r\n let hydrogens = Atom.maxBonds[neighbour.value.element] - neighbour.value.bondCount;\r\n let charge = '';\r\n\r\n if (neighbour.value.bracket) {\r\n hydrogens = neighbour.value.bracket.hcount;\r\n charge = neighbour.value.bracket.charge || 0;\r\n }\r\n\r\n vertex.value.attachPseudoElement(neighbour.value.element, previous ? previous.value.element : null, hydrogens, charge);\r\n }\r\n }\r\n\r\n // The second pass\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const atom = vertex.value;\r\n const element = atom.element;\r\n\r\n if (element === 'C' || element === 'H' || !atom.isDrawn) {\r\n continue;\r\n }\r\n\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j].value;\r\n\r\n if (!neighbour.hasAttachedPseudoElements || neighbour.getAttachedPseudoElementsCount() !== 2) {\r\n continue;\r\n }\r\n\r\n const pseudoElements = neighbour.getAttachedPseudoElements();\r\n\r\n if (pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\r\n neighbour.isDrawn = false;\r\n vertex.value.attachPseudoElement('Ac', '', 0);\r\n }\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.graph.getDecays();\r\n }\r\n\r\n buildBlockSmiles() {\r\n return this.graph.buildSmiles();\r\n }\r\n\r\n /**\r\n * Find edge and mark it as decay point and redraw graph\r\n * @param e event\r\n */\r\n handleMouseClick(e) {\r\n if (this.opts.drawDecayPoints === DecayState.VALUES.NO) {\r\n return;\r\n }\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (!this.graph) {\r\n return;\r\n }\r\n this.findAndReDrawEdge(e.clientX - this.opts.offsetX, e.clientY - this.opts.offsetY + (document.documentElement.scrollTop || document.body.scrollTop));\r\n }\r\n\r\n /**\r\n * Find edge which was clicked, mark edge as decay point and redraw graph\r\n * @param mouseX mouse positionX - offsetX\r\n * @param mouseY mouse positionY - offsetY\r\n */\r\n findAndReDrawEdge(mouseX, mouseY) {\r\n for (let i = 0; i < this.graph.edges.length; ++i) {\r\n let vertexA = this.graph.vertices[this.graph.edges[i].sourceId];\r\n let vertexB = this.graph.vertices[this.graph.edges[i].targetId];\r\n if (!vertexA || !vertexB) {\r\n continue;\r\n }\r\n let scale = this.computeScale();\r\n let line = new Line(vertexA.position, vertexB.position, null, null, false, false, true);\r\n let l = this.computeEdgeLeftPoint(line, scale);\r\n let r = this.computeEdgeRightPoint(line, scale);\r\n if (mouseX < l.x - this.opts.mouseTolerance || mouseX > r.x + this.opts.mouseTolerance) {\r\n continue;\r\n }\r\n if ((mouseY > l.y - this.opts.mouseTolerance && mouseY < r.y + this.opts.mouseTolerance)\r\n || (mouseY > r.y - this.opts.mouseTolerance && mouseY < l.y + this.opts.mouseTolerance)) {\r\n this.reDrawGraphWithEdgeAsDecay(i);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Make edge decay point and redraw graph\r\n * @param {Number} edgeId\r\n */\r\n reDrawGraphWithEdgeAsDecay(edgeId) {\r\n this.graph.revertEdgeDecayPoint(edgeId);\r\n this.canvasWrapper.updateSize(this.opts.width, this.opts.height);\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n }\r\n\r\n /**\r\n * Compute scale of canvas\r\n * @return {number} scale\r\n */\r\n computeScale() {\r\n let scaleX = this.canvasWrapper.canvas.offsetWidth / this.canvasWrapper.drawingWidth;\r\n let scaleY = this.canvasWrapper.canvas.offsetHeight / this.canvasWrapper.drawingHeight;\r\n return (scaleX < scaleY) ? scaleX : scaleY;\r\n }\r\n\r\n /**\r\n * Compute left point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeLeftPoint(line, scale) {\r\n return this.computeEdgePoint(line.getLeftVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute right point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeRightPoint(line, scale) {\r\n return this.computeEdgePoint(line.getRightVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute point coordinates for compare\r\n * add offset to coordinates and multiply coordinates with scale\r\n * @param {Vector2} point\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgePoint(point, scale) {\r\n point.x += this.canvasWrapper.offsetX;\r\n point.y += this.canvasWrapper.offsetY;\r\n point.x *= scale;\r\n point.y *= scale;\r\n return point;\r\n }\r\n}\r\n\r\nmodule.exports = Drawer;\r\n","//@ts-check\r\n\r\n/** \r\n * A class representing an edge. \r\n * \r\n * @property {Number} id The id of this edge.\r\n * @property {Number} sourceId The id of the source vertex.\r\n * @property {Number} targetId The id of the target vertex.\r\n * @property {Number} weight The weight of this edge. That is, the degree of the bond (single bond = 1, double bond = 2, etc).\r\n * @property {String} [bondType='-'] The bond type of this edge.\r\n * @property {Boolean} [isPartOfAromaticRing=false] Whether or not this edge is part of an aromatic ring.\r\n * @property {Boolean} [center=false] Wheter or not the bond is centered. For example, this affects straight double bonds.\r\n * @property {String} [wedge=''] Wedge direction. Either '', 'up' or 'down'\r\n */\r\nclass Edge {\r\n /**\r\n * The constructor for the class Edge.\r\n *\r\n * @param {Number} sourceId A vertex id.\r\n * @param {Number} targetId A vertex id.\r\n * @param {Number} [weight=1] The weight of the edge.\r\n */\r\n constructor(sourceId, targetId, weight = 1) {\r\n this.id = null;\r\n this.sourceId = sourceId;\r\n this.targetId = targetId;\r\n this.weight = weight;\r\n this.bondType = '-';\r\n this.isPartOfAromaticRing = false;\r\n this.center = false;\r\n this.wedge = '';\r\n this.isDecay = false;\r\n this.isDecayAll = false;\r\n }\r\n\r\n /**\r\n * Set the bond type of this edge. This also sets the edge weight.\r\n * @param {String} bondType \r\n */\r\n setBondType(bondType) {\r\n this.bondType = bondType;\r\n this.weight = Edge.bonds[bondType];\r\n }\r\n\r\n /**\r\n * Set decay\r\n * @param {Boolean} decay point\r\n */\r\n setDecay(decay) {\r\n this.isDecay = decay;\r\n }\r\n\r\n /**\r\n * Set decay All\r\n * @param {Boolean} decay point\r\n */\r\n setDecayAll(decay) {\r\n this.isDecayAll = decay;\r\n }\r\n\r\n /**\r\n * An object mapping the bond type to the number of bonds.\r\n *\r\n * @returns {Object} The object containing the map.\r\n */\r\n static get bonds() {\r\n return {\r\n '-': 1,\r\n '/': 1,\r\n '\\\\': 1,\r\n '=': 2,\r\n '#': 3,\r\n '$': 4\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Edge;\r\n","//@ts-check\r\nconst DecayPoint = require('./DecayPoint');\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Ring = require('./Ring');\r\nconst Atom = require('./Atom');\r\nconst VertexState = require('./VertexState');\r\nconst SmallGraph = require('./SmallGraph');\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst DecayState = require('./DecayState');\r\nconst MutableBoolean = require('./MutableBoolean');\r\nconst MutableCounter = require('./MutableCounter');\r\nconst Direction = require('./Direction');\r\n\r\n/**\r\n * A class representing the molecular graph.\r\n *\r\n * @property {Vertex[]} vertices The vertices of the graph.\r\n * @property {Edge[]} edges The edges of this graph.\r\n * @property {Number[]} decays The id of edges marked as decay point of this graph.\r\n * @property {Object} vertexIdsToEdgeId A map mapping vertex ids to the edge between the two vertices. The key is defined as vertexAId + '_' + vertexBId.\r\n * @property {Boolean} isometric A boolean indicating whether or not the SMILES associated with this graph is isometric.\r\n */\r\nclass Graph {\r\n /**\r\n * The constructor of the class Graph.\r\n *\r\n * @param {Object} parseTree A SMILES parse tree.\r\n * @param {Boolean} [isomeric=false] A boolean specifying whether or not the SMILES is isomeric.\r\n * @param options\r\n */\r\n constructor(parseTree, isomeric = false, options = {}) {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.decays = Array();\r\n this.decaysAll = Array();\r\n this.vertexIdsToEdgeId = {};\r\n this.isomeric = isomeric;\r\n this._startingVertexes = [];\r\n this._isCyclic = false;\r\n this._polyketide = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.options = options;\r\n this._componentsIsPolyketide = [];\r\n\r\n // Used for the bridge detection algorithm\r\n this._time = 0;\r\n this._init(parseTree);\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION. Initializing the graph from the parse tree.\r\n *\r\n * @param {Object} node The current node in the parse tree.\r\n * @param order\r\n * @param {Number} parentVertexId=null The id of the previous vertex.\r\n * @param {Boolean} isBranch=false Whether or not the bond leading to this vertex is a branch bond. Branches are represented by parentheses in smiles (e.g. CC(O)C).\r\n */\r\n _init(node, order = 0, parentVertexId = null, isBranch = false) {\r\n // Create a new vertex object\r\n let atom = new Atom(node.atom.element ? node.atom.element : node.atom, node.bond);\r\n\r\n atom.branchBond = node.branchBond;\r\n atom.ringbonds = node.ringbonds;\r\n atom.bracket = node.atom.element ? node.atom : null;\r\n\r\n let vertex = new Vertex(atom);\r\n let parentVertex = this.vertices[parentVertexId];\r\n\r\n this.addVertex(vertex);\r\n\r\n // Add the id of this node to the parent as child\r\n if (parentVertexId !== null) {\r\n vertex.setParentVertexId(parentVertexId);\r\n vertex.value.addNeighbouringElement(parentVertex.value.element);\r\n parentVertex.addChild(vertex.id);\r\n parentVertex.value.addNeighbouringElement(atom.element);\r\n\r\n // In addition create a spanningTreeChildren property, which later will\r\n // not contain the children added through ringbonds\r\n parentVertex.spanningTreeChildren.push(vertex.id);\r\n\r\n // Add edge between this node and its parent\r\n let edge = new Edge(parentVertexId, vertex.id, 1);\r\n let vertexId;\r\n\r\n if (isBranch) {\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n } else {\r\n edge.setBondType(parentVertex.value.bondType || '-');\r\n vertexId = parentVertex.id;\r\n }\r\n\r\n this.addEdge(edge);\r\n }\r\n\r\n let offset = node.ringbondCount + 1;\r\n\r\n if (atom.bracket) {\r\n offset += atom.bracket.hcount;\r\n }\r\n\r\n let stereoHydrogens = 0;\r\n if (atom.bracket && atom.bracket.chirality) {\r\n atom.isStereoCenter = true;\r\n stereoHydrogens = atom.bracket.hcount;\r\n for (var i = 0; i < stereoHydrogens; i++) {\r\n this._init({\r\n atom: 'H',\r\n isBracket: 'false',\r\n branches: Array(),\r\n branchCount: 0,\r\n ringbonds: Array(),\r\n ringbondCount: false,\r\n next: null,\r\n hasNext: false,\r\n bond: '-'\r\n }, i, vertex.id, true);\r\n }\r\n }\r\n\r\n for (var i = 0; i < node.branchCount; i++) {\r\n this._init(node.branches[i], i + offset, vertex.id, true);\r\n }\r\n\r\n if (node.hasNext) {\r\n this._init(node.next, node.branchCount + offset, vertex.id);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of molecule\r\n * Types of decay points, declared in DecayPoint\r\n */\r\n findDecayPoints() {\r\n if (!Object.keys(this.options).length) {\r\n return;\r\n }\r\n\r\n switch (this.options.drawDecayPoints) {\r\n default:\r\n case DecayState.VALUES.NO:\r\n return;\r\n case DecayState.VALUES.STANDARD:\r\n this.standardDecays();\r\n break;\r\n case DecayState.VALUES.SOURCE:\r\n this.sourceDecays();\r\n break;\r\n case DecayState.VALUES.STANDARD_AND_SOURCE:\r\n this.standardDecays();\r\n this.sourceDecays();\r\n break;\r\n }\r\n }\r\n\r\n reduceDecays() {\r\n this._decaysCopy = [];\r\n this.dfsSmilesInitialization();\r\n for (let i = 0; i < this.decays.length; i++) {\r\n this.smallBlockDfsStart(this.edges[this.decays[i]]);\r\n }\r\n this.decays = [];\r\n this.decays = this._decaysCopy;\r\n this.setStandardDecays();\r\n }\r\n\r\n dfsSmallInitialization(vertices) {\r\n for (let i = 0; i < vertices.length; ++i) {\r\n this.vertices[vertices[i]].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n smallBlockDfsStart(edge) {\r\n let stackVisitedVertexes = [];\r\n let depth = this.smallDfs(this.vertices[edge.sourceId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n stackVisitedVertexes = [];\r\n depth = this.smallDfs(this.vertices[edge.targetId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n this._decaysCopy.push(edge.id);\r\n }\r\n }\r\n }\r\n\r\n smallDfs(vertex, depth, stackVisitedVertexes) {\r\n stackVisitedVertexes.push(vertex.id);\r\n if (depth > 3) {\r\n return depth;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return depth;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n ++depth;\r\n\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n depth = this.smallDfs(this.vertices[nextVertex], depth, stackVisitedVertexes);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n return depth;\r\n }\r\n\r\n setStandardDecays() {\r\n this.edges.forEach(e => {\r\n e.setDecay(false);\r\n });\r\n this.decays.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n });\r\n }\r\n\r\n standardDecays() {\r\n for (let i = 0; i < this.edges.length; i++) {\r\n if (this.edges[i].bondType === '=') {\r\n let dec = this.isDecayPoint(this.edges[i].sourceId, this.edges[i].targetId, i);\r\n if (dec !== false) {\r\n this.edges[dec].setDecay(true);\r\n this.decays.push(dec);\r\n this.edges[dec].setDecayAll(true);\r\n this.decaysAll.push(dec);\r\n }\r\n }\r\n }\r\n this.reduceDecays();\r\n }\r\n\r\n sourceDecays() {\r\n this.options.decaySource.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n this.edges[e].setDecayAll(true);\r\n this.decays.push(e);\r\n this.decaysAll.push(e);\r\n });\r\n }\r\n\r\n /**\r\n * check if its decay point of specific decay types\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @param decayTypes DecayPoint\r\n * @returns {int|boolean} return edge id when found, otherwise return false\r\n */\r\n isDecayPoint(sourceId, targetId, edgeBondId, decayTypes = DecayPoint.VALUES.ALL) {\r\n switch (decayTypes) {\r\n case DecayPoint.VALUES.ALL:\r\n let found = this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n if (found === false) {\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n } else {\r\n return found;\r\n }\r\n case DecayPoint.VALUES.COO:\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n case DecayPoint.VALUES.CONH:\r\n return this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-O- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'O', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'O', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-NH- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'N', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'N', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay point edge id of right neighbour\r\n * @param vertexId\r\n * @param element\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayId(vertexId, element, edgeBondId) {\r\n for (let i = 0; i < this.vertices[vertexId].edges.length; i++) {\r\n let edgeId = this.checkNeighbourEdgeId(this.vertices[vertexId].edges[i], vertexId, element);\r\n if (edgeId !== false && edgeId !== edgeBondId) {\r\n return edgeId;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find edge id of decay point\r\n * @param edgeId\r\n * @param vertexId\r\n * @param element\r\n * @returns {int|boolean}\r\n */\r\n checkNeighbourEdgeId(edgeId, vertexId, element) {\r\n if ((this.edges[edgeId].sourceId === vertexId && this.vertices[this.edges[edgeId].targetId].value.element === element) ||\r\n (this.edges[edgeId].targetId === vertexId && this.vertices[this.edges[edgeId].sourceId].value.element === element)) {\r\n return edgeId;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clears all the elements in this graph (edges and vertices).\r\n */\r\n clear() {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.vertexIdsToEdgeId = {};\r\n }\r\n\r\n /**\r\n * Add a vertex to the graph.\r\n *\r\n * @param {Vertex} vertex A new vertex.\r\n * @returns {Number} The vertex id of the new vertex.\r\n */\r\n addVertex(vertex) {\r\n vertex.id = this.vertices.length;\r\n this.vertices.push(vertex);\r\n\r\n return vertex.id;\r\n }\r\n\r\n /**\r\n * Add an edge to the graph.\r\n *\r\n * @param {Edge} edge A new edge.\r\n * @returns {Number} The edge id of the new edge.\r\n */\r\n addEdge(edge) {\r\n let source = this.vertices[edge.sourceId];\r\n let target = this.vertices[edge.targetId];\r\n\r\n edge.id = this.edges.length;\r\n this.edges.push(edge);\r\n\r\n this.vertexIdsToEdgeId[edge.sourceId + '_' + edge.targetId] = edge.id;\r\n this.vertexIdsToEdgeId[edge.targetId + '_' + edge.sourceId] = edge.id;\r\n edge.isPartOfAromaticRing = source.value.isPartOfAromaticRing && target.value.isPartOfAromaticRing;\r\n\r\n source.value.bondCount += edge.weight;\r\n target.value.bondCount += edge.weight;\r\n\r\n source.edges.push(edge.id);\r\n target.edges.push(edge.id);\r\n\r\n return edge.id;\r\n }\r\n\r\n /**\r\n * Returns the edge between two given vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {(Edge|null)} The edge or, if no edge can be found, null.\r\n */\r\n getEdge(vertexIdA, vertexIdB) {\r\n let edgeId = this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB];\r\n\r\n return edgeId === undefined ? null : this.edges[edgeId];\r\n }\r\n\r\n /**\r\n * Returns the ids of edges connected to a vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Number[]} An array containing the ids of edges connected to the vertex.\r\n */\r\n getEdges(vertexId) {\r\n let edgeIds = Array();\r\n let vertex = this.vertices[vertexId];\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n edgeIds.push(this.vertexIdsToEdgeId[vertexId + '_' + vertex.neighbours[i]]);\r\n }\r\n\r\n return edgeIds;\r\n }\r\n\r\n\r\n /**\r\n * Check whether or not two vertices are connected by an edge.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not two vertices are connected by an edge.\r\n */\r\n hasEdge(vertexIdA, vertexIdB) {\r\n return this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB] !== undefined\r\n }\r\n\r\n /**\r\n * Returns an array containing the vertex ids of this graph.\r\n *\r\n * @returns {Number[]} An array containing all vertex ids of this graph.\r\n */\r\n getVertexList() {\r\n let arr = [this.vertices.length];\r\n\r\n for (var i = 0; i < this.vertices.length; i++) {\r\n arr[i] = this.vertices[i].id;\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array containing source, target arrays of this graphs edges.\r\n *\r\n * @returns {Array[]} An array containing source, target arrays of this graphs edges. Example: [ [ 2, 5 ], [ 6, 9 ] ].\r\n */\r\n getEdgeList() {\r\n let arr = Array(this.edges.length);\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n arr[i] = [this.edges[i].sourceId, this.edges[i].targetId];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph.\r\n */\r\n getAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph with all bridges removed (thus the components). Thus the remaining vertices are all part of ring systems.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph with all bridges removed.\r\n */\r\n getComponentsAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n let bridges = this.getBridges();\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n for (var i = 0; i < bridges.length; i++) {\r\n adjacencyMatrix[bridges[i][0]][bridges[i][1]] = 0;\r\n adjacencyMatrix[bridges[i][1]][bridges[i][0]] = 0;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency matrix of the subgraph.\r\n */\r\n getSubgraphAdjacencyMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyMatrix[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of the graph.\r\n *\r\n * @returns {Array[]} The distance matrix of the graph.\r\n */\r\n getDistanceMatrix() {\r\n let length = this.vertices.length;\r\n let adja = this.getAdjacencyMatrix();\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The distance matrix of the subgraph.\r\n */\r\n getSubgraphDistanceMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adja = this.getSubgraphAdjacencyMatrix(vertexIds);\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of the graph.\r\n *\r\n * @returns {Array[]} The adjancency list of the graph.\r\n */\r\n getAdjacencyList() {\r\n let length = this.vertices.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = [];\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(this.vertices[i].id, this.vertices[j].id)) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency list of the subgraph.\r\n */\r\n getSubgraphAdjacencyList(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = Array();\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Returns an array containing the edge ids of bridges. A bridge splits the graph into multiple components when removed.\r\n *\r\n * @returns {Number[]} An array containing the edge ids of the bridges.\r\n */\r\n getBridges() {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n let disc = new Array(length);\r\n let low = new Array(length);\r\n let parent = new Array(length);\r\n let adj = this.getAdjacencyList();\r\n let outBridges = Array();\r\n\r\n visited.fill(false);\r\n parent.fill(null);\r\n this._time = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (!visited[i]) {\r\n this._bridgeDfs(i, visited, disc, low, parent, adj, outBridges);\r\n }\r\n }\r\n\r\n return outBridges;\r\n }\r\n\r\n /**\r\n * Traverses the graph in breadth-first order.\r\n *\r\n * @param {Number} startVertexId The id of the starting vertex.\r\n * @param {Function} callback The callback function to be called on every vertex.\r\n */\r\n traverseBF(startVertexId, callback) {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n\r\n visited.fill(false);\r\n\r\n var queue = [startVertexId];\r\n\r\n while (queue.length > 0) {\r\n // JavaScripts shift() is O(n) ... bad JavaScript, bad!\r\n let u = queue.shift();\r\n let vertex = this.vertices[u];\r\n\r\n callback(vertex);\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n let v = vertex.neighbours[i];\r\n if (!visited[v]) {\r\n visited[v] = true;\r\n queue.push(v);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the depth of a subtree in the direction opposite to the vertex specified as the parent vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId The id of a neighbouring vertex.\r\n * @returns {Number} The depth of the sub-tree.\r\n */\r\n getTreeDepth(vertexId, parentVertexId) {\r\n if (vertexId === null || parentVertexId === null) {\r\n return 0;\r\n }\r\n\r\n let neighbours = this.vertices[vertexId].getSpanningTreeNeighbours(parentVertexId);\r\n let max = 0;\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n let childId = neighbours[i];\r\n let d = this.getTreeDepth(childId, vertexId);\r\n\r\n if (d > max) {\r\n max = d;\r\n }\r\n }\r\n\r\n return max + 1;\r\n }\r\n\r\n /**\r\n * Traverse a sub-tree in the graph.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId A neighbouring vertex.\r\n * @param {Function} callback The callback function that is called with each visited as an argument.\r\n * @param {Number} [maxDepth=999999] The maximum depth of the recursion.\r\n * @param {Boolean} [ignoreFirst=false] Whether or not to ignore the starting vertex supplied as vertexId in the callback.\r\n * @param {Number} [depth=1] The current depth in the tree.\r\n * @param {Uint8Array} [visited=null] An array holding a flag on whether or not a node has been visited.\r\n */\r\n traverseTree(vertexId, parentVertexId, callback, maxDepth = 999999, ignoreFirst = false, depth = 1, visited = null) {\r\n if (visited === null) {\r\n visited = new Uint8Array(this.vertices.length);\r\n }\r\n\r\n if (depth > maxDepth + 1 || visited[vertexId] === 1) {\r\n return;\r\n }\r\n\r\n visited[vertexId] = 1;\r\n\r\n let vertex = this.vertices[vertexId];\r\n let neighbours = vertex.getNeighbours(parentVertexId);\r\n\r\n if (!ignoreFirst || depth > 1) {\r\n callback(vertex);\r\n }\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n this.traverseTree(neighbours[i], vertexId, callback, maxDepth, ignoreFirst, depth + 1, visited);\r\n }\r\n }\r\n\r\n /**\r\n * Positiones the (sub)graph using Kamada and Kawais algorithm for drawing general undirected graphs. https://pdfs.semanticscholar.org/b8d3/bca50ccc573c5cb99f7d201e8acce6618f04.pdf\r\n * There are undocumented layout parameters. They are undocumented for a reason, so be very careful.\r\n *\r\n * @param {Number[]} vertexIds An array containing vertexIds to be placed using the force based layout.\r\n * @param {Vector2} center The center of the layout.\r\n * @param {Number} startVertexId A vertex id. Should be the starting vertex - e.g. the first to be positioned and connected to a previously place vertex.\r\n * @param {Ring} ring The bridged ring associated with this force-based layout.\r\n */\r\n kkLayout(vertexIds, center, startVertexId, ring, bondLength,\r\n threshold = 0.1, innerThreshold = 0.1, maxIteration = 2000,\r\n maxInnerIteration = 50, maxEnergy = 1e9) {\r\n\r\n let edgeStrength = bondLength;\r\n\r\n // Add vertices that are directly connected to the ring\r\n var i = vertexIds.length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n var j = vertex.neighbours.length;\r\n }\r\n\r\n let matDist = this.getSubgraphDistanceMatrix(vertexIds);\r\n let length = vertexIds.length;\r\n\r\n // Initialize the positions. Place all vertices on a ring around the center\r\n let radius = MathHelper.polyCircumradius(500, length);\r\n let angle = MathHelper.centralAngle(length);\r\n let a = 0.0;\r\n let arrPositionX = new Float32Array(length);\r\n let arrPositionY = new Float32Array(length);\r\n let arrPositioned = Array(length);\r\n\r\n i = length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n if (!vertex.positioned) {\r\n arrPositionX[i] = center.x + Math.cos(a) * radius;\r\n arrPositionY[i] = center.y + Math.sin(a) * radius;\r\n } else {\r\n arrPositionX[i] = vertex.position.x;\r\n arrPositionY[i] = vertex.position.y;\r\n }\r\n arrPositioned[i] = vertex.positioned;\r\n a += angle;\r\n }\r\n\r\n // Create the matrix containing the lengths\r\n let matLength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matLength[i] = new Array(length);\r\n var j = length;\r\n while (j--) {\r\n matLength[i][j] = bondLength * matDist[i][j];\r\n }\r\n }\r\n\r\n // Create the matrix containing the spring strenghts\r\n let matStrength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matStrength[i] = Array(length);\r\n var j = length;\r\n while (j--) {\r\n matStrength[i][j] = edgeStrength * Math.pow(matDist[i][j], -2.0);\r\n }\r\n }\r\n\r\n // Create the matrix containing the energies\r\n let matEnergy = Array(length);\r\n let arrEnergySumX = new Float32Array(length);\r\n let arrEnergySumY = new Float32Array(length);\r\n i = length;\r\n while (i--) {\r\n matEnergy[i] = Array(length);\r\n }\r\n\r\n i = length;\r\n let ux, uy, dEx, dEy, vx, vy, denom;\r\n\r\n while (i--) {\r\n ux = arrPositionX[i];\r\n uy = arrPositionY[i];\r\n dEx = 0.0;\r\n dEy = 0.0;\r\n let j = length;\r\n while (j--) {\r\n if (i === j) {\r\n continue;\r\n }\r\n vx = arrPositionX[j];\r\n vy = arrPositionY[j];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n matEnergy[i][j] = [\r\n matStrength[i][j] * ((ux - vx) - matLength[i][j] * (ux - vx) * denom),\r\n matStrength[i][j] * ((uy - vy) - matLength[i][j] * (uy - vy) * denom)\r\n ];\r\n matEnergy[j][i] = matEnergy[i][j];\r\n dEx += matEnergy[i][j][0];\r\n dEy += matEnergy[i][j][1];\r\n }\r\n arrEnergySumX[i] = dEx;\r\n arrEnergySumY[i] = dEy;\r\n }\r\n\r\n // Utility functions, maybe inline them later\r\n let energy = function (index) {\r\n return [arrEnergySumX[index] * arrEnergySumX[index] + arrEnergySumY[index] * arrEnergySumY[index], arrEnergySumX[index], arrEnergySumY[index]];\r\n };\r\n\r\n let highestEnergy = function () {\r\n let maxEnergy = 0.0;\r\n let maxEnergyId = 0;\r\n let maxDEX = 0.0;\r\n let maxDEY = 0.0;\r\n\r\n i = length;\r\n while (i--) {\r\n let [delta, dEX, dEY] = energy(i);\r\n\r\n if (delta > maxEnergy && arrPositioned[i] === false) {\r\n maxEnergy = delta;\r\n maxEnergyId = i;\r\n maxDEX = dEX;\r\n maxDEY = dEY;\r\n }\r\n }\r\n\r\n return [maxEnergyId, maxEnergy, maxDEX, maxDEY];\r\n };\r\n\r\n let update = function (index, dEX, dEY) {\r\n let dxx = 0.0;\r\n let dyy = 0.0;\r\n let dxy = 0.0;\r\n let ux = arrPositionX[index];\r\n let uy = arrPositionY[index];\r\n let arrL = matLength[index];\r\n let arrK = matStrength[index];\r\n\r\n i = length;\r\n while (i--) {\r\n if (i === index) {\r\n continue;\r\n }\r\n\r\n let vx = arrPositionX[i];\r\n let vy = arrPositionY[i];\r\n let l = arrL[i];\r\n let k = arrK[i];\r\n let m = (ux - vx) * (ux - vx);\r\n let denom = 1.0 / Math.pow(m + (uy - vy) * (uy - vy), 1.5);\r\n\r\n dxx += k * (1 - l * (uy - vy) * (uy - vy) * denom);\r\n dyy += k * (1 - l * m * denom);\r\n dxy += k * (l * (ux - vx) * (uy - vy) * denom);\r\n }\r\n\r\n // Prevent division by zero\r\n if (dxx === 0) {\r\n dxx = 0.1;\r\n }\r\n\r\n if (dyy === 0) {\r\n dyy = 0.1;\r\n }\r\n\r\n if (dxy === 0) {\r\n dxy = 0.1;\r\n }\r\n\r\n let dy = (dEX / dxx + dEY / dxy);\r\n dy /= (dxy / dxx - dyy / dxy); // had to split this onto two lines because the syntax highlighter went crazy.\r\n let dx = -(dxy * dy + dEX) / dxx;\r\n\r\n arrPositionX[index] += dx;\r\n arrPositionY[index] += dy;\r\n\r\n // Update the energies\r\n let arrE = matEnergy[index];\r\n dEX = 0.0;\r\n dEY = 0.0;\r\n\r\n ux = arrPositionX[index];\r\n uy = arrPositionY[index];\r\n\r\n let vx, vy, prevEx, prevEy, denom;\r\n\r\n i = length;\r\n while (i--) {\r\n if (index === i) {\r\n continue;\r\n }\r\n vx = arrPositionX[i];\r\n vy = arrPositionY[i];\r\n // Store old energies\r\n prevEx = arrE[i][0];\r\n prevEy = arrE[i][1];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n dx = arrK[i] * ((ux - vx) - arrL[i] * (ux - vx) * denom);\r\n dy = arrK[i] * ((uy - vy) - arrL[i] * (uy - vy) * denom);\r\n\r\n arrE[i] = [dx, dy];\r\n dEX += dx;\r\n dEY += dy;\r\n arrEnergySumX[i] += dx - prevEx;\r\n arrEnergySumY[i] += dy - prevEy;\r\n }\r\n arrEnergySumX[index] = dEX;\r\n arrEnergySumY[index] = dEY;\r\n };\r\n\r\n // Setting up variables for the while loops\r\n let maxEnergyId = 0;\r\n let dEX = 0.0;\r\n let dEY = 0.0;\r\n let delta = 0.0;\r\n let iteration = 0;\r\n let innerIteration = 0;\r\n\r\n while (maxEnergy > threshold && maxIteration > iteration) {\r\n iteration++;\r\n [maxEnergyId, maxEnergy, dEX, dEY] = highestEnergy();\r\n delta = maxEnergy;\r\n innerIteration = 0;\r\n while (delta > innerThreshold && maxInnerIteration > innerIteration) {\r\n innerIteration++;\r\n update(maxEnergyId, dEX, dEY);\r\n [delta, dEX, dEY] = energy(maxEnergyId);\r\n }\r\n }\r\n\r\n i = length;\r\n while (i--) {\r\n let index = vertexIds[i];\r\n let vertex = this.vertices[index];\r\n vertex.position.x = arrPositionX[i];\r\n vertex.position.y = arrPositionY[i];\r\n vertex.positioned = true;\r\n vertex.forcePositioned = true;\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getBridges().\r\n */\r\n _bridgeDfs(u, visited, disc, low, parent, adj, outBridges) {\r\n visited[u] = true;\r\n disc[u] = low[u] = ++this._time;\r\n\r\n for (var i = 0; i < adj[u].length; i++) {\r\n let v = adj[u][i];\r\n\r\n if (!visited[v]) {\r\n parent[v] = u;\r\n\r\n this._bridgeDfs(v, visited, disc, low, parent, adj, outBridges);\r\n\r\n low[u] = Math.min(low[u], low[v]);\r\n\r\n // If low > disc, we have a bridge\r\n if (low[v] > disc[u]) {\r\n outBridges.push([u, v]);\r\n }\r\n } else if (v !== parent[u]) {\r\n low[u] = Math.min(low[u], disc[v]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the connected components of the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Set[]} Connected components as sets.\r\n */\r\n static getConnectedComponents(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let components = [];\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n let component = Array();\r\n visited[u] = true;\r\n component.push(u);\r\n count++;\r\n Graph._ccGetDfs(u, visited, adjacencyMatrix, component);\r\n if (component.length > 1) {\r\n components.push(component);\r\n }\r\n }\r\n }\r\n\r\n return components;\r\n }\r\n\r\n /**\r\n * Returns the number of connected components for the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of connected components of the supplied graph.\r\n */\r\n static getConnectedComponentCount(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n visited[u] = true;\r\n count++;\r\n Graph._ccCountDfs(u, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponentCount().\r\n */\r\n static _ccCountDfs(u, visited, adjacencyMatrix) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n Graph._ccCountDfs(v, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponents().\r\n */\r\n static _ccGetDfs(u, visited, adjacencyMatrix, component) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n component.push(v);\r\n Graph._ccGetDfs(v, visited, adjacencyMatrix, component);\r\n }\r\n }\r\n\r\n /**\r\n * Revert decay point value and update list of decay points\r\n * when edge isn't decay point -> change mark edge as decay point and add edge to decays list\r\n * when edge is decay point -> unmark edge as decay point and remove edgeId from list of decays\r\n * @param edgeId\r\n */\r\n revertEdgeDecayPoint(edgeId) {\r\n this.edges[edgeId].isDecay = !this.edges[edgeId].isDecay;\r\n this.edges[edgeId].isDecayAll = !this.edges[edgeId].isDecayAll;\r\n if (this.edges[edgeId].isDecay) {\r\n this.decays.push(edgeId);\r\n this.decaysAll.push(edgeId);\r\n } else {\r\n let index = this.decays.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decays.splice(index, 1);\r\n }\r\n index = this.decaysAll.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decaysAll.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.decays;\r\n }\r\n\r\n /**\r\n * Build block of SMILES based on decay points\r\n * DFS pass through graph\r\n * but the numbers are already setup in vertex.value.ringbonds array so no need to second pass of dfs\r\n */\r\n buildSmiles() {\r\n let smiles = [];\r\n this._polyketide = false;\r\n this.dfsSmilesInitialization();\r\n if (this.decays.length === 0) {\r\n this.startDfs(this.vertices[0], smiles);\r\n return {blockSmiles: smiles, sequence: '[0]', sequenceType: SequenceType.VALUES.OTHER, decays: this.decays, isPolyketide: this._polyketide};\r\n } else {\r\n this.dfsBuildSmilesStart(smiles);\r\n }\r\n this.dfsSmilesInitialization();\r\n this.dfsSmallStart();\r\n this._smallGraph.oneCyclic();\r\n this._smallGraph.dfsSequenceStart();\r\n let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence);\r\n return {\r\n blockSmiles: sequenceData.smiles,\r\n sequence: sequenceData.sequence,\r\n sequenceType: this._smallGraph.sequenceType + ((this._smallGraph.sequenceType === 'linear' || this._smallGraph.sequenceType === 'cyclic') && this._polyketide ? '-polyketide' : ''),\r\n decays: this.decays,\r\n isPolyketide: this._polyketide\r\n }\r\n }\r\n\r\n sortSequence(smiles, sequence) {\r\n let permutation = this.getSequencePermutation(sequence);\r\n let newSmiles = new Array(permutation.length).fill(null);\r\n for (let i = 0; i < permutation.length; ++i) {\r\n newSmiles[i] = smiles[permutation[i][0]];\r\n }\r\n\r\n let position = 0;\r\n let char = sequence.charAt(position);\r\n let newSequence = '';\r\n while (true) {\r\n switch (char) {\r\n case '0':\r\n case '1':\r\n case '2':\r\n case '3':\r\n case '4':\r\n case '5':\r\n case '6':\r\n case '7':\r\n case '8':\r\n case '9':\r\n let number = char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n while(!isNaN(char)) {\r\n number += char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n let j;\r\n for (j = 0; j < permutation.length; ++j) {\r\n if (permutation[j][0] === number) {\r\n newSequence += j;\r\n break;\r\n }\r\n }\r\n continue;\r\n default:\r\n newSequence += char;\r\n }\r\n\r\n ++position;\r\n if (position >= sequence.length) {\r\n break;\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n return {sequence: newSequence, smiles: newSmiles};\r\n }\r\n\r\n getSequencePermutation(sequence) {\r\n let re = /\\d+/g;\r\n let match = null;\r\n let permutation = [];\r\n while ((match = re.exec(sequence)) != null) {\r\n permutation.push(match);\r\n }\r\n return permutation;\r\n }\r\n\r\n dfsSmallStart() {\r\n this._smallGraph = new SmallGraph();\r\n for (let index = 0; index < this._startingVertexes.length; ++index) {\r\n this._smallGraph.addVertex(new Node(this._startingVertexes[index].component));\r\n this.first = this._startingVertexes[index];\r\n this.dfsSmall(this._startingVertexes[index], this._componentsIsPolyketide[index]);\r\n }\r\n }\r\n\r\n /**\r\n * Initialize graph for dfs\r\n * set for all vertices vertexState to NotFound\r\n */\r\n dfsSmilesInitialization() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n /**\r\n * Starting function for DFS\r\n * starts on decay points (on edge), so start on both side of edge\r\n * @param {Array} smiles output param, array of SMILES blocks (string)\r\n */\r\n dfsBuildSmilesStart(smiles) {\r\n this._cnt = 0;\r\n this._markComponent = false;\r\n this._startingVertexes = [];\r\n for (let i = 0; i < this.decays.length; ++i) {\r\n let edge = this.edges[this.decays[i]];\r\n this.markingComponents(this.startDfs(this.vertices[edge.sourceId], smiles));\r\n this.markingComponents(this.startDfs(this.vertices[edge.targetId], smiles));\r\n }\r\n }\r\n\r\n markingComponents(isPolyketyde) {\r\n if (this._markComponent) {\r\n this._cnt++;\r\n this._markComponent = false;\r\n this._componentsIsPolyketide.push(isPolyketyde);\r\n }\r\n }\r\n\r\n /**\r\n * Start DFS for build SMILES of blocks\r\n * @param {Vertex} vertex to start DFS\r\n * @param {Array} smiles output param, array od SMILES\r\n */\r\n startDfs(vertex, smiles) {\r\n let isPolyketide = new MutableBoolean(true);\r\n let decaysCounter = new MutableCounter();\r\n let vertexCounter = new MutableCounter();\r\n let through = [];\r\n let stackSmiles = [];\r\n this.first = vertex.id;\r\n this._isCyclic = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.dfsSmiles(vertex, stackSmiles, isPolyketide, decaysCounter, through, vertexCounter);\r\n if (decaysCounter.getValue() < 2 && isPolyketide.getValue() === true) {\r\n isPolyketide.setValue(through.every(vertex => vertex === 'O' || vertex === 'N') && vertexCounter.getValue() > 4);\r\n }\r\n if (this._isCyclic) {\r\n this.closedToNotFound();\r\n stackSmiles = [];\r\n this.dfsSmiles(vertex, stackSmiles, new MutableBoolean(true), new MutableCounter(), [], new MutableCounter(), -1, true);\r\n }\r\n this.closedToFullyClosed();\r\n\r\n stackSmiles = Graph.removeUnnecessaryParentheses(stackSmiles);\r\n let smile = Graph.removeUnnecessaryNumbers(stackSmiles.join(\"\"));\r\n if (smile.length !== 0) {\r\n smiles.push({smiles: smile, isPolyketide: isPolyketide.getValue()});\r\n if (isPolyketide.getValue() === true) {\r\n this._polyketide = true;\r\n }\r\n }\r\n return isPolyketide.getValue();\r\n }\r\n\r\n closedToNotFound() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n }\r\n\r\n closedToFullyClosed() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.FULLY_CLOSED;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * DFS for SMILES\r\n * @param {Vertex} vertex\r\n * @param {Array} stackSmiles output param\r\n * @param {MutableBoolean} isPolyketide\r\n * @param {MutableCounter} cntDecays\r\n * @param {Array} through\r\n * @param {MutableCounter} vertexCounter\r\n * @param lastVertexId last vertex id for setup digits\r\n * @param isSecondPass is second pass of dfs\r\n */\r\n dfsSmiles(vertex, stackSmiles, isPolyketide, cntDecays, through, vertexCounter, lastVertexId = -1, isSecondPass = false) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN && !isSecondPass && lastVertexId !== -1) {\r\n this._isCyclic = true;\r\n if (!vertex.digits.some(e => this.vertices[lastVertexId].digits.includes(e))) {\r\n vertex.digits.push(this._digitCounter);\r\n this.vertices[lastVertexId].digits.push(this._digitCounter);\r\n this._digitCounter++;\r\n }\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n if (vertex.value.element === 'H') {\r\n return;\r\n }\r\n\r\n if (this.first === vertex.id && vertex.value.element === \"C\" && isPolyketide.getValue()) {\r\n stackSmiles.push(\"O\");\r\n isPolyketide.setValue(false);\r\n }\r\n\r\n if (vertex.value.bracket) {\r\n stackSmiles.push(\"[\");\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n if (vertex.value.bracket.hcount > 0) {\r\n stackSmiles.push('H');\r\n if (vertex.value.bracket.hcount > 1) {\r\n stackSmiles.push(vertex.value.bracket.hcount);\r\n }\r\n }\r\n if (vertex.value.bracket.charge > 0) {\r\n stackSmiles.push('+');\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n } else if (vertex.value.bracket.charge < 0) {\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n }\r\n stackSmiles.push(\"]\");\r\n } else {\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n }\r\n vertexCounter.increment();\r\n\r\n if (isSecondPass) {\r\n stackSmiles.push(this.smilesNumbersAdd(vertex));\r\n }\r\n\r\n if (!this._markComponent) {\r\n this._startingVertexes.push(vertex);\r\n }\r\n vertex.component = this._cnt;\r\n this._markComponent = true;\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n if (edge.isDecayAll && lastVertexId !== nextVertex) {\r\n through.push(vertex.value.element);\r\n }\r\n if (edge.isDecay) {\r\n cntDecays.increment();\r\n if (vertex.value.element === \"C\" && vertex.id !== this.first && isPolyketide.getValue()) {\r\n stackSmiles.push(\"(\");\r\n stackSmiles.push(\"O\");\r\n stackSmiles.push(\")\");\r\n isPolyketide.setValue(false);\r\n }\r\n continue;\r\n }\r\n stackSmiles.push(\"(\");\r\n Graph.addBondTypeToStack(edge, stackSmiles);\r\n if (lastVertexId !== nextVertex) {\r\n this.dfsSmiles(this.vertices[nextVertex], stackSmiles, isPolyketide, cntDecays, through, vertexCounter, vertex.id, isSecondPass);\r\n }\r\n Graph.checkStack(stackSmiles);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSmall(vertex, isPolyketide) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n\r\n this._smallGraph.addNeighbour(vertex.component, this.vertices[Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId)].component, Direction.getProperValue(isPolyketide, vertex.value.element, vertex.id, this.first));\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n this.dfsSmall(this.vertices[nextVertex], isPolyketide);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n\r\n static printVertexValue(stackSmiles, vertex) {\r\n if (vertex.value.isPartOfAromaticRing) {\r\n stackSmiles.push(vertex.value.element.toLowerCase());\r\n } else {\r\n stackSmiles.push(vertex.value.element);\r\n }\r\n }\r\n\r\n /**\r\n * Remove numbers which is neighbours in SMILES notation -> need to perform in cyclic structures\r\n * @param {String} smiles SMILES\r\n * @return {String} repaired SMILES\r\n */\r\n static removeUnnecessaryNumbers(smiles) {\r\n if (smiles === null) {\r\n return '';\r\n }\r\n try {\r\n let numbers = this.getNumbers(smiles);\r\n for (let number of numbers) {\r\n let first = this.findFirst(smiles, number);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n let tmpRange = this.removeRangeLast(smiles, first, second, number);\r\n smiles = this.repairSmiles(smiles, tmpRange, first, second, number);\r\n }\r\n return smiles;\r\n } catch (ex) {\r\n return smiles;\r\n }\r\n }\r\n\r\n /**\r\n * Remove unnecessary numbers from SMILES\r\n * @param {String} smiles\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {*}\r\n */\r\n static removeNumbers(smiles, first, second, number) {\r\n if (number > 9) {\r\n let numLength = number.toString().length;\r\n smiles = smiles.slice(0, first - 1) + smiles.slice(first + numLength);\r\n return smiles.slice(0, second - 2 - numLength) + smiles.slice(second - 1);\r\n } else {\r\n smiles = smiles.slice(0, first) + smiles.slice(first + 1);\r\n return smiles.slice(0, second - 1) + smiles.slice(second);\r\n }\r\n }\r\n\r\n /**\r\n * Reapair SMILES\r\n * @param {String} smiles\r\n * @param {String} tmpRange\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {String|*}\r\n */\r\n static repairSmiles(smiles, tmpRange, first, second, number) {\r\n let pattern = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])$\");\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let patternOrg = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])\");\r\n if (patternOrg.test(tmpRange)) {\r\n return smiles;\r\n }\r\n\r\n while (tmpRange.length !== 0) {\r\n if (tmpRange[0] === '(') {\r\n tmpRange = tmpRange.substring(1);\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let leftBrackets = 1;\r\n let rightBrackets = 0;\r\n while (leftBrackets !== rightBrackets) {\r\n switch (tmpRange[0]) {\r\n case '(':\r\n leftBrackets++;\r\n break;\r\n case ')':\r\n rightBrackets++;\r\n break;\r\n }\r\n if (\"\" === tmpRange) {\r\n return smiles;\r\n }\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n return this.repairSmiles(smiles, tmpRange, first, second, number);\r\n } else {\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Substring in range and remove last Organic Subset\r\n * @param smiles\r\n * @param first\r\n * @param second\r\n * @param number\r\n * @return {string}\r\n */\r\n static removeRangeLast(smiles, first, second, number) {\r\n if (number > 9) {\r\n return smiles.substring(first + number.toString().length, second - 1);\r\n } else {\r\n return smiles.substring(first + 1, second);\r\n }\r\n }\r\n\r\n /**\r\n * Get numbers from SMILES\r\n * @param smiles\r\n * @return {Set}\r\n */\r\n static getNumbers(smiles) {\r\n let numbers = new Set();\r\n for (let index = 0; index < smiles.length; ++index) {\r\n if (!isNaN(smiles[index])) {\r\n numbers.add(smiles[index]);\r\n } else if (smiles[index] === '%') {\r\n index++;\r\n let num = \"\";\r\n while (!isNaN(smiles[index])) {\r\n num += smiles[index];\r\n index++;\r\n if (index >= smiles.length) {\r\n break;\r\n }\r\n }\r\n index--;\r\n numbers.add(num);\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * return index of first occurrence number\r\n * @param smiles\r\n * @param number\r\n * @return {number}\r\n */\r\n static findFirst(smiles, number) {\r\n return smiles.indexOf(number);\r\n }\r\n\r\n /**\r\n * return index of first occurrence number from index + 1\r\n * @param smiles\r\n * @param from range no including this point (from, Infinity) = [from + 1, Infinity)\r\n * @param number\r\n * @return {*}\r\n */\r\n static findSecond(smiles, from, number) {\r\n let result = smiles.indexOf(number, from);\r\n if (result === -1) {\r\n throw \"Not Found\";\r\n }\r\n return result;\r\n }\r\n\r\n\r\n smilesNumbersAdd(vertex) {\r\n let numbers = '';\r\n for (let i = 0; i < vertex.digits.length; ++i) {\r\n let num = vertex.digits[i];\r\n if (this._printedDigits.some(e => e === num)) {\r\n let nextVertex = this.vertices.find(e => e.digits.includes(num) && e.id !== vertex.id);\r\n let intersection = vertex.edges.filter(element => nextVertex.edges.includes(element));\r\n\r\n if (intersection.length > 0) {\r\n let bond = this.edges[intersection[0]].bondType;\r\n if (bond !== '-') {\r\n numbers += bond;\r\n }\r\n }\r\n }\r\n\r\n this._printedDigits.push(num);\r\n let numString = num.toString();\r\n if (numString.length === 1) {\r\n numbers += numString;\r\n } else {\r\n numbers += '%' + numString;\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * Return other vertex id then the actual vertex id\r\n * when vertexId === sourceId return targetId\r\n * when vertexId === targetId return sourceId\r\n * @param {Number} vertexId actual vertex id\r\n * @param {Number} sourceId source vertex id\r\n * @param {Number} targetId target vertex id\r\n * @return {Number}\r\n */\r\n static getProperVertex(vertexId, sourceId, targetId) {\r\n if (vertexId === sourceId) return targetId;\r\n else return sourceId;\r\n }\r\n\r\n static repairNumbers(smiles) {\r\n try {\r\n let numbers = Array.from(this.getNumbers(smiles));\r\n numbers.sort(function (a, b) {\r\n return b - a\r\n });\r\n\r\n let index = 1;\r\n for (let number of numbers) {\r\n if (index === number) {\r\n continue;\r\n }\r\n let first = this.findFirst(smiles, number);\r\n if (number > 9) {\r\n smiles = smiles.slice(0, first - 1) + index + smiles.slice(first + number.toString().length);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second - 1) + index + smiles.slice(second + number.toString().length);\r\n } else {\r\n smiles = smiles.slice(0, first) + index + smiles.slice(first + 1);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second) + index + smiles.slice(second + 1);\r\n }\r\n index++;\r\n }\r\n } catch (e) {\r\n return smiles;\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from SMILES\r\n * example CCC(CC)(C) -> CCC(CC)C\r\n * example C(=O)C(C(C)) -> C(=O)CCC\r\n * @param {Array} stackRight\r\n * @return {Array}\r\n */\r\n static removeUnnecessaryParentheses(stackRight) {\r\n if (stackRight.length === 0) return [];\r\n let stackLeft = [], lastLiteral = \"\", literal = \"\";\r\n while (stackRight.length > 0) {\r\n literal = stackRight.shift();\r\n if ((\")\".localeCompare(literal) === 0 && \")\".localeCompare(lastLiteral) === 0)) {\r\n Graph.removeParentheses(stackLeft, false, literal);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n lastLiteral = literal;\r\n }\r\n\r\n literal = stackLeft.pop();\r\n if ((\")\".localeCompare(literal) === 0 && stackRight.length === 0)) {\r\n Graph.removeParentheses(stackLeft);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n return stackLeft;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from stack\r\n * go through stack and when find proper closing bracket,\r\n * then remove it and push back removed data when searching in stack\r\n * @param {Array} stack with unnecessary parentheses to remove\r\n * @param {Boolean} end treat with situation when \")\" is last character of stack -> end = true, else where end = false\r\n * @param {String} literal, when end = false, need to pop from stack and at the end add literal back to stack\r\n */\r\n static removeParentheses(stack, end = true, literal = \"\") {\r\n let stackTmp = [];\r\n let leftBraces = 0, rightBraces = 1;\r\n if (!end) {\r\n stack.pop();\r\n }\r\n while (true) {\r\n let lit = stack.pop();\r\n if (\"(\".localeCompare(lit) === 0) {\r\n leftBraces++;\r\n } else if (\")\".localeCompare(lit) === 0) {\r\n rightBraces++;\r\n }\r\n if (leftBraces === rightBraces) {\r\n Graph.moveAllValuesInStackToAnotherStack(stackTmp, stack);\r\n if (!end) {\r\n stack.push(literal);\r\n }\r\n break;\r\n }\r\n stackTmp.push(lit);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all values from stackSource and push it to stackDestination\r\n * @param {Array} stackSource stack to remove values\r\n * @param {Array} stackDestination stack to add values from stackSource\r\n */\r\n static moveAllValuesInStackToAnotherStack(stackSource, stackDestination) {\r\n while (stackSource.length > 0) {\r\n stackDestination.push(stackSource.pop());\r\n }\r\n }\r\n\r\n /**\r\n * Check last value of stack\r\n * if it one of (, -, = or # then remove all characters in stack to first ( from the end of stack\r\n * elsewhere add ) to stack\r\n * @param {Array} stackSmiles\r\n */\r\n static checkStack(stackSmiles) {\r\n switch (stackSmiles[stackSmiles.length - 1]) {\r\n case \"(\":\r\n case \"-\":\r\n case \"=\":\r\n case \"#\":\r\n Graph.removeAllFromStackToFirstLeftBrace(stackSmiles);\r\n break;\r\n default:\r\n stackSmiles.push(\")\");\r\n }\r\n }\r\n\r\n /**\r\n * Remove all characters from stack to first \"(\"\r\n * @param {Array} stackSmiles\r\n */\r\n static removeAllFromStackToFirstLeftBrace(stackSmiles) {\r\n let literal = stackSmiles.pop();\r\n while (literal !== \"(\") {\r\n if (stackSmiles.length === 0) break;\r\n literal = stackSmiles.pop();\r\n }\r\n }\r\n\r\n /**\r\n * Add bond type to stack\r\n * if edge have = or # bond type add it to stack\r\n * @param {Edge} edge\r\n * @param {Array} stackSmiles\r\n */\r\n static addBondTypeToStack(edge, stackSmiles) {\r\n if (edge.bondType === \"=\" || edge.bondType === \"#\") {\r\n stackSmiles.push(edge.bondType);\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Graph;\r\n","//@ts-check\r\nconst Vector2 = require('./Vector2')\r\n\r\n/** \r\n * A class representing a line.\r\n * \r\n * @property {Vector2} from The Vector2 defining the start of the line.\r\n * @property {Vector2} to The Vector2 defining the end of the line.\r\n * @property {String} elementFrom The element symbol associated with the start of the line.\r\n * @property {String} elementTo The element symbol associated with the end of the line.\r\n * @property {Boolean} chiralFrom A boolean indicating whether or not the source atom is a chiral center.\r\n * @property {Boolean} chiralTo A boolean indicating whether or tno the target atom is a chiral center.\r\n */\r\nclass Line {\r\n /**\r\n * The constructor for the class Line.\r\n *\r\n * @param {Vector2} [from=new Vector2(0, 0)] A vector marking the beginning of the line.\r\n * @param {Vector2} [to=new Vector2(0, 0)] A vector marking the end of the line.\r\n * @param {string} [elementFrom=null] A one-letter representation of the element associated with the vector marking the beginning of the line.\r\n * @param {string} [elementTo=null] A one-letter representation of the element associated with the vector marking the end of the line.\r\n * @param {Boolean} [chiralFrom=false] Whether or not the from atom is a chiral center.\r\n * @param {Boolean} [chiralTo=false] Whether or not the to atom is a chiral center.\r\n * @param {Boolean} [isDecayPoint=false] Whether or not the edge is a decay point\r\n */\r\n constructor(from = new Vector2(0,0), to = new Vector2(0, 0), elementFrom = null, elementTo = null, chiralFrom = false, chiralTo = false, isDecayPoint = false) {\r\n this.from = from;\r\n this.to = to;\r\n this.elementFrom = elementFrom;\r\n this.elementTo = elementTo;\r\n this.chiralFrom = chiralFrom;\r\n this.chiralTo = chiralTo;\r\n this.isDecayPoint = isDecayPoint;\r\n }\r\n\r\n /**\r\n * Clones this line and returns the clone.\r\n *\r\n * @returns {Line} A clone of this line.\r\n */\r\n clone() {\r\n return new Line(this.from.clone(), this.to.clone(), this.elementFrom, this.elementTo);\r\n }\r\n\r\n /**\r\n * Returns the length of this line.\r\n *\r\n * @returns {Number} The length of this line.\r\n */\r\n getLength() {\r\n return Math.sqrt(Math.pow(this.to.x - this.from.x, 2) + \r\n Math.pow(this.to.y - this.from.y, 2));\r\n }\r\n\r\n\r\n /**\r\n * Returns the angle of the line in relation to the coordinate system (the x-axis).\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n // Get the angle between the line and the x-axis\r\n let diff = Vector2.subtract(this.getRightVector(), this.getLeftVector());\r\n return diff.angle();\r\n }\r\n\r\n /**\r\n * Returns the right vector (the vector with the larger x value).\r\n *\r\n * @returns {Vector2} The right vector.\r\n */\r\n getRightVector() {\r\n // Return the vector with the larger x value (the right one)\r\n if (this.from.x < this.to.x) {\r\n return this.to;\r\n } else {\r\n return this.from;\r\n }\r\n }\r\n \r\n /**\r\n * Returns the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {Vector2} The left vector.\r\n */\r\n getLeftVector() {\r\n // Return the vector with the smaller x value (the left one)\r\n if (this.from.x < this.to.x) {\r\n return this.from;\r\n } else {\r\n return this.to;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the right vector (the vector with the larger x value).\r\n *\r\n * @returns {String} The element associated with the right vector.\r\n */\r\n getRightElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementTo;\r\n } else {\r\n return this.elementFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {String} The element associated with the left vector.\r\n */\r\n getLeftElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementFrom;\r\n } else {\r\n return this.elementTo;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the right vector (the vector with the larger x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the right vector is a chiral center.\r\n */\r\n getRightChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralTo;\r\n } else {\r\n return this.chiralFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the left vector (the vector with the smaller x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the left vector is a chiral center.\r\n */\r\n getLeftChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralFrom;\r\n } else {\r\n return this.chiralTo;\r\n }\r\n }\r\n\r\n /**\r\n * Set the value of the right vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setRightVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.to.x = x;\r\n this.to.y = y;\r\n } else {\r\n this.from.x = x;\r\n this.from.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Set the value of the left vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setLeftVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.from.x = x;\r\n this.from.y = y;\r\n } else {\r\n this.to.x = x;\r\n this.to.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this line to be aligned with the x-axis. The center of rotation is the left vector.\r\n *\r\n * @returns {Line} This line.\r\n */\r\n rotateToXAxis() {\r\n let left = this.getLeftVector();\r\n \r\n this.setRightVector(left.x + this.getLength(), left.y);\r\n \r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate the line by a given value (in radians). The center of rotation is the left vector.\r\n *\r\n * @param {Number} theta The angle (in radians) to rotate the line.\r\n * @returns {Line} This line.\r\n */\r\n rotate(theta) {\r\n let l = this.getLeftVector();\r\n let r = this.getRightVector();\r\n let sinTheta = Math.sin(theta);\r\n let cosTheta = Math.cos(theta);\r\n\r\n let x = cosTheta * (r.x - l.x) - sinTheta * (r.y - l.y) + l.x;\r\n let y = sinTheta * (r.x - l.x) - cosTheta * (r.y - l.y) + l.y;\r\n \r\n this.setRightVector(x, y);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"from\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenFrom(by) {\r\n let f = Vector2.subtract(this.to, this.from);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.from.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"to\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenTo(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.to.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shorten the right side.\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenRight(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenTo(by);\r\n } else {\r\n this.shortenFrom(by);\r\n }\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Shorten the left side.\r\n * \r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenLeft(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenFrom(by);\r\n } else {\r\n this.shortenTo(by);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from both directions by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shorten(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by / 2.0);\r\n \r\n this.to.add(f);\r\n this.from.subtract(f);\r\n\r\n return this;\r\n }\r\n}\r\n\r\nmodule.exports = Line;","/** \r\n * A static class containing helper functions for math-related tasks. \r\n */\r\nclass MathHelper {\r\n /**\r\n * Rounds a value to a given number of decimals.\r\n *\r\n * @static\r\n * @param {Number} value A number.\r\n * @param {Number} decimals The number of decimals.\r\n * @returns {Number} A number rounded to a given number of decimals.\r\n */\r\n static round(value, decimals) {\r\n decimals = decimals ? decimals : 1;\r\n return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);\r\n }\r\n\r\n /**\r\n * Returns the means of the angles contained in an array. In radians.\r\n *\r\n * @static\r\n * @param {Number[]} arr An array containing angles (in radians).\r\n * @returns {Number} The mean angle in radians.\r\n */\r\n static meanAngle(arr) {\r\n let sin = 0.0;\r\n let cos = 0.0;\r\n \r\n for (var i = 0; i < arr.length; i++) {\r\n sin += Math.sin(arr[i]);\r\n cos += Math.cos(arr[i]);\r\n }\r\n\r\n return Math.atan2(sin / arr.length, cos / arr.length);\r\n }\r\n\r\n /**\r\n * Returns the inner angle of a n-sided regular polygon.\r\n *\r\n * @static\r\n * @param {Number} n Number of sides of a regular polygon.\r\n * @returns {Number} The inner angle of a given regular polygon.\r\n */\r\n static innerAngle(n) {\r\n return MathHelper.toRad((n - 2) * 180 / n);\r\n }\r\n\r\n /**\r\n * Returns the circumradius of a n-sided regular polygon with a given side-length.\r\n *\r\n * @static\r\n * @param {Number} s The side length of the regular polygon.\r\n * @param {Number} n The number of sides.\r\n * @returns {Number} The circumradius of the regular polygon.\r\n */\r\n static polyCircumradius(s, n) {\r\n return s / (2 * Math.sin(Math.PI / n));\r\n }\r\n\r\n /**\r\n * Returns the apothem of a regular n-sided polygon based on its radius.\r\n *\r\n * @static\r\n * @param {Number} r The radius.\r\n * @param {Number} n The number of edges of the regular polygon.\r\n * @returns {Number} The apothem of a n-sided polygon based on its radius.\r\n */\r\n static apothem(r, n) {\r\n return r * Math.cos(Math.PI / n);\r\n }\r\n\r\n static apothemFromSideLength(s, n) {\r\n let r = MathHelper.polyCircumradius(s, n);\r\n \r\n return MathHelper.apothem(r, n);\r\n }\r\n\r\n /**\r\n * The central angle of a n-sided regular polygon. In radians.\r\n *\r\n * @static\r\n * @param {Number} n The number of sides of the regular polygon.\r\n * @returns {Number} The central angle of the n-sided polygon in radians.\r\n */\r\n static centralAngle(n) {\r\n return MathHelper.toRad(360 / n);\r\n }\r\n\r\n /**\r\n * Convertes radians to degrees.\r\n *\r\n * @static\r\n * @param {Number} rad An angle in radians.\r\n * @returns {Number} The angle in degrees.\r\n */\r\n static toDeg(rad) {\r\n return rad * MathHelper.degFactor;\r\n }\r\n\r\n /**\r\n * Converts degrees to radians.\r\n *\r\n * @static\r\n * @param {Number} deg An angle in degrees.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static toRad(deg) {\r\n return deg * MathHelper.radFactor;\r\n }\r\n\r\n /**\r\n * Returns the parity of the permutation (1 or -1)\r\n * @param {(Array|Uint8Array)} arr An array containing the permutation.\r\n * @returns {Number} The parity of the permutation (1 or -1), where 1 means even and -1 means odd.\r\n */\r\n static parityOfPermutation(arr) {\r\n let visited = new Uint8Array(arr.length);\r\n let evenLengthCycleCount = 0;\r\n\r\n let traverseCycle = function(i, cycleLength = 0) {\r\n if (visited[i] === 1) {\r\n return cycleLength;\r\n }\r\n\r\n cycleLength++;\r\n\r\n visited[i] = 1;\r\n return traverseCycle(arr[i], cycleLength);\r\n }\r\n\r\n for (var i = 0; i < arr.length; i++) {\r\n if (visited[i] === 1) {\r\n continue;\r\n }\r\n\r\n let cycleLength = traverseCycle(i);\r\n evenLengthCycleCount += (1 - cycleLength % 2);\r\n }\r\n\r\n return evenLengthCycleCount % 2 ? -1 : 1;\r\n }\r\n\r\n /** The factor to convert degrees to radians. */\r\n static get radFactor() {\r\n return Math.PI / 180.0;\r\n }\r\n\r\n /** The factor to convert radians to degrees. */\r\n static get degFactor() {\r\n return 180.0 / Math.PI;\r\n }\r\n\r\n /** Two times PI. */\r\n static get twoPI() {\r\n return 2.0 * Math.PI;\r\n }\r\n}\r\n\r\nmodule.exports = MathHelper;","/**\r\n *@property {boolean} value is boolean\r\n */\r\nclass MutableBoolean {\r\n\r\n /**\r\n * @param {boolean} value\r\n */\r\n constructor(value) {\r\n this.value = value;\r\n }\r\n\r\n setValue(value) {\r\n this.value = value;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableBoolean;\r\n","/**\r\n * @param {Number} value\r\n */\r\nclass MutableCounter {\r\n\r\n constructor() {\r\n this.value = 0;\r\n }\r\n\r\n increment() {\r\n this.value++;\r\n }\r\n\r\n reset() {\r\n this.value = 0;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableCounter;\r\n","\r\nclass Neighbour {\r\n\r\n constructor(neighbour, direction) {\r\n this.neighbour = neighbour;\r\n this.direction = direction;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Neighbour;\r\n","//@ts-check\r\nconst VertexState = require(\"./VertexState\");\r\n\r\nclass Node {\r\n\r\n constructor(id) {\r\n this.id = id;\r\n this.neighbours = [];\r\n this.onRing = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n\r\n addNeighbour(neighbour) {\r\n this.neighbours.push(neighbour);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Node;\r\n","// WHEN REPLACING, CHECK FOR:\r\n// KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\nmodule.exports = (function () {\r\n \"use strict\";\r\n\r\n /*\r\n * Generated by PEG.js 0.10.0.\r\n *\r\n * http://pegjs.org/\r\n */\r\n\r\n function peg$subclass(child, parent) {\r\n function ctor() {\r\n this.constructor = child;\r\n }\r\n ctor.prototype = parent.prototype;\r\n child.prototype = new ctor();\r\n }\r\n\r\n function peg$SyntaxError(message, expected, found, location) {\r\n this.message = message;\r\n this.expected = expected;\r\n this.found = found;\r\n this.location = location;\r\n this.name = \"SyntaxError\";\r\n\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(this, peg$SyntaxError);\r\n }\r\n }\r\n\r\n peg$subclass(peg$SyntaxError, Error);\r\n\r\n peg$SyntaxError.buildMessage = function (expected, found) {\r\n var DESCRIBE_EXPECTATION_FNS = {\r\n literal: function (expectation) {\r\n return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";\r\n },\r\n\r\n \"class\": function (expectation) {\r\n var escapedParts = \"\",\r\n i;\r\n\r\n for (i = 0; i < expectation.parts.length; i++) {\r\n escapedParts += expectation.parts[i] instanceof Array ?\r\n classEscape(expectation.parts[i][0]) + \"-\" + classEscape(expectation.parts[i][1]) :\r\n classEscape(expectation.parts[i]);\r\n }\r\n\r\n return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";\r\n },\r\n\r\n any: function (expectation) {\r\n return \"any character\";\r\n },\r\n\r\n end: function (expectation) {\r\n return \"end of input\";\r\n },\r\n\r\n other: function (expectation) {\r\n return expectation.description;\r\n }\r\n };\r\n\r\n function hex(ch) {\r\n return ch.charCodeAt(0).toString(16).toUpperCase();\r\n }\r\n\r\n function literalEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function classEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\\]/g, '\\\\]')\r\n .replace(/\\^/g, '\\\\^')\r\n .replace(/-/g, '\\\\-')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function describeExpectation(expectation) {\r\n return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\r\n }\r\n\r\n function describeExpected(expected) {\r\n var descriptions = new Array(expected.length),\r\n i, j;\r\n\r\n for (i = 0; i < expected.length; i++) {\r\n descriptions[i] = describeExpectation(expected[i]);\r\n }\r\n\r\n descriptions.sort();\r\n\r\n if (descriptions.length > 0) {\r\n for (i = 1, j = 1; i < descriptions.length; i++) {\r\n if (descriptions[i - 1] !== descriptions[i]) {\r\n descriptions[j] = descriptions[i];\r\n j++;\r\n }\r\n }\r\n descriptions.length = j;\r\n }\r\n\r\n switch (descriptions.length) {\r\n case 1:\r\n return descriptions[0];\r\n\r\n case 2:\r\n return descriptions[0] + \" or \" + descriptions[1];\r\n\r\n default:\r\n return descriptions.slice(0, -1).join(\", \") +\r\n \", or \" +\r\n descriptions[descriptions.length - 1];\r\n }\r\n }\r\n\r\n function describeFound(found) {\r\n return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";\r\n }\r\n\r\n return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\r\n };\r\n\r\n function peg$parse(input, options) {\r\n options = options !== void 0 ? options : {};\r\n\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n var nOpenParentheses = input.split('(').length - 1;\r\n var nCloseParentheses = input.split(')').length - 1;\r\n\r\n if (nOpenParentheses !== nCloseParentheses) {\r\n throw peg$buildSimpleError('The number of opening parentheses does not match the number of closing parentheses.', 0);\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n var peg$FAILED = {},\r\n\r\n peg$startRuleFunctions = {\r\n chain: peg$parsechain\r\n },\r\n peg$startRuleFunction = peg$parsechain,\r\n\r\n peg$c0 = function (s) {\r\n var branches = [];\r\n var rings = [];\r\n\r\n for (var i = 0; i < s[1].length; i++) {\r\n branches.push(s[1][i]);\r\n }\r\n\r\n\r\n for (var i = 0; i < s[2].length; i++) {\r\n var bond = (s[2][i][0]) ? s[2][i][0] : '-';\r\n rings.push({\r\n 'bond': bond,\r\n 'id': s[2][i][1]\r\n });\r\n }\r\n\r\n for (var i = 0; i < s[3].length; i++) {\r\n branches.push(s[3][i]);\r\n }\r\n\r\n for (var i = 0; i < s[6].length; i++) {\r\n branches.push(s[6][i]);\r\n }\r\n\r\n return {\r\n 'atom': s[0],\r\n 'isBracket': s[0].element ? true : false,\r\n 'branches': branches,\r\n 'branchCount': branches.length,\r\n 'ringbonds': rings,\r\n 'ringbondCount': rings.length,\r\n 'bond': s[4] ? s[4] : '-',\r\n 'next': s[5],\r\n 'hasNext': s[5] ? true : false\r\n }\r\n\r\n return s;\r\n },\r\n peg$c1 = \"(\",\r\n peg$c2 = peg$literalExpectation(\"(\", false),\r\n peg$c3 = \")\",\r\n peg$c4 = peg$literalExpectation(\")\", false),\r\n peg$c5 = function (b) {\r\n var bond = (b[1]) ? b[1] : '-';\r\n b[2].branchBond = bond;\r\n return b[2]\r\n },\r\n peg$c6 = function (a) {\r\n return a;\r\n },\r\n peg$c7 = /^[\\-=#$:\\/\\\\.]/,\r\n peg$c8 = peg$classExpectation([\"-\", \"=\", \"#\", \"$\", \":\", \"/\", \"\\\\\", \".\"], false, false),\r\n peg$c9 = function (b) {\r\n return b;\r\n },\r\n peg$c10 = \"[\",\r\n peg$c11 = peg$literalExpectation(\"[\", false),\r\n peg$c12 = \"se\",\r\n peg$c13 = peg$literalExpectation(\"se\", false),\r\n peg$c14 = \"as\",\r\n peg$c15 = peg$literalExpectation(\"as\", false),\r\n peg$c16 = \"]\",\r\n peg$c17 = peg$literalExpectation(\"]\", false),\r\n peg$c18 = function (b) {\r\n return {\r\n 'isotope': b[1],\r\n 'element': b[2],\r\n 'chirality': b[3],\r\n 'hcount': b[4],\r\n 'charge': b[5],\r\n 'class': b[6]\r\n }\r\n },\r\n peg$c19 = \"B\",\r\n peg$c20 = peg$literalExpectation(\"B\", false),\r\n peg$c21 = \"r\",\r\n peg$c22 = peg$literalExpectation(\"r\", false),\r\n peg$c23 = \"C\",\r\n peg$c24 = peg$literalExpectation(\"C\", false),\r\n peg$c25 = \"l\",\r\n peg$c26 = peg$literalExpectation(\"l\", false),\r\n peg$c27 = /^[NOPSFI]/,\r\n peg$c28 = peg$classExpectation([\"N\", \"O\", \"P\", \"S\", \"F\", \"I\"], false, false),\r\n peg$c29 = function (o) {\r\n if (o.length > 1) return o.join('');\r\n return o;\r\n },\r\n peg$c30 = /^[bcnops]/,\r\n peg$c31 = peg$classExpectation([\"b\", \"c\", \"n\", \"o\", \"p\", \"s\"], false, false),\r\n peg$c32 = \"*\",\r\n peg$c33 = peg$literalExpectation(\"*\", false),\r\n peg$c34 = function (w) {\r\n return w;\r\n },\r\n peg$c35 = /^[A-Z]/,\r\n peg$c36 = peg$classExpectation([\r\n [\"A\", \"Z\"]\r\n ], false, false),\r\n peg$c37 = /^[a-z]/,\r\n peg$c38 = peg$classExpectation([\r\n [\"a\", \"z\"]\r\n ], false, false),\r\n peg$c39 = function (e) {\r\n return e.join('');\r\n },\r\n peg$c40 = \"%\",\r\n peg$c41 = peg$literalExpectation(\"%\", false),\r\n peg$c42 = /^[1-9]/,\r\n peg$c43 = peg$classExpectation([\r\n [\"1\", \"9\"]\r\n ], false, false),\r\n peg$c44 = /^[0-9]/,\r\n peg$c45 = peg$classExpectation([\r\n [\"0\", \"9\"]\r\n ], false, false),\r\n peg$c46 = function (r) {\r\n if (r.length == 1) return Number(r);\r\n return Number(r.join('').replace('%', ''));\r\n },\r\n peg$c47 = \"@\",\r\n peg$c48 = peg$literalExpectation(\"@\", false),\r\n peg$c49 = \"TH\",\r\n peg$c50 = peg$literalExpectation(\"TH\", false),\r\n peg$c51 = /^[12]/,\r\n peg$c52 = peg$classExpectation([\"1\", \"2\"], false, false),\r\n peg$c53 = \"AL\",\r\n peg$c54 = peg$literalExpectation(\"AL\", false),\r\n peg$c55 = \"SP\",\r\n peg$c56 = peg$literalExpectation(\"SP\", false),\r\n peg$c57 = /^[1-3]/,\r\n peg$c58 = peg$classExpectation([\r\n [\"1\", \"3\"]\r\n ], false, false),\r\n peg$c59 = \"TB\",\r\n peg$c60 = peg$literalExpectation(\"TB\", false),\r\n peg$c61 = \"OH\",\r\n peg$c62 = peg$literalExpectation(\"OH\", false),\r\n peg$c63 = function (c) {\r\n if (!c[1]) return '@';\r\n if (c[1] == '@') return '@@';\r\n\r\n return c[1].join('').replace(',', '');\r\n },\r\n peg$c64 = function (c) {\r\n return c;\r\n },\r\n peg$c65 = \"+\",\r\n peg$c66 = peg$literalExpectation(\"+\", false),\r\n peg$c67 = function (c) {\r\n if (!c[1]) return 1;\r\n if (c[1] != '+') return Number(c[1].join(''));\r\n return 2;\r\n },\r\n peg$c68 = \"-\",\r\n peg$c69 = peg$literalExpectation(\"-\", false),\r\n peg$c70 = function (c) {\r\n if (!c[1]) return -1;\r\n if (c[1] != '-') return -Number(c[1].join(''));\r\n return -2;\r\n },\r\n peg$c71 = \"H\",\r\n peg$c72 = peg$literalExpectation(\"H\", false),\r\n peg$c73 = function (h) {\r\n if (h[1]) return Number(h[1]);\r\n return 1;\r\n },\r\n peg$c74 = \":\",\r\n peg$c75 = peg$literalExpectation(\":\", false),\r\n peg$c76 = /^[0]/,\r\n peg$c77 = peg$classExpectation([\"0\"], false, false),\r\n peg$c78 = function (c) {\r\n return Number(c[1][0] + c[1][1].join(''));\r\n },\r\n peg$c79 = function (i) {\r\n return Number(i.join(''));\r\n },\r\n\r\n peg$currPos = 0,\r\n peg$savedPos = 0,\r\n peg$posDetailsCache = [{\r\n line: 1,\r\n column: 1\r\n }],\r\n peg$maxFailPos = 0,\r\n peg$maxFailExpected = [],\r\n peg$silentFails = 0,\r\n\r\n peg$result;\r\n\r\n if (\"startRule\" in options) {\r\n if (!(options.startRule in peg$startRuleFunctions)) {\r\n throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");\r\n }\r\n\r\n peg$startRuleFunction = peg$startRuleFunctions[options.startRule];\r\n }\r\n\r\n function text() {\r\n return input.substring(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function location() {\r\n return peg$computeLocation(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function expected(description, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildStructuredError(\r\n [peg$otherExpectation(description)],\r\n input.substring(peg$savedPos, peg$currPos),\r\n location\r\n );\r\n }\r\n\r\n function error(message, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildSimpleError(message, location);\r\n }\r\n\r\n function peg$literalExpectation(text, ignoreCase) {\r\n return {\r\n type: \"literal\",\r\n text: text,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$classExpectation(parts, inverted, ignoreCase) {\r\n return {\r\n type: \"class\",\r\n parts: parts,\r\n inverted: inverted,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$anyExpectation() {\r\n return {\r\n type: \"any\"\r\n };\r\n }\r\n\r\n function peg$endExpectation() {\r\n return {\r\n type: \"end\"\r\n };\r\n }\r\n\r\n function peg$otherExpectation(description) {\r\n return {\r\n type: \"other\",\r\n description: description\r\n };\r\n }\r\n\r\n function peg$computePosDetails(pos) {\r\n var details = peg$posDetailsCache[pos],\r\n p;\r\n\r\n if (details) {\r\n return details;\r\n } else {\r\n p = pos - 1;\r\n while (!peg$posDetailsCache[p]) {\r\n p--;\r\n }\r\n\r\n details = peg$posDetailsCache[p];\r\n details = {\r\n line: details.line,\r\n column: details.column\r\n };\r\n\r\n while (p < pos) {\r\n if (input.charCodeAt(p) === 10) {\r\n details.line++;\r\n details.column = 1;\r\n } else {\r\n details.column++;\r\n }\r\n\r\n p++;\r\n }\r\n\r\n peg$posDetailsCache[pos] = details;\r\n return details;\r\n }\r\n }\r\n\r\n function peg$computeLocation(startPos, endPos) {\r\n var startPosDetails = peg$computePosDetails(startPos),\r\n endPosDetails = peg$computePosDetails(endPos);\r\n\r\n return {\r\n start: {\r\n offset: startPos,\r\n line: startPosDetails.line,\r\n column: startPosDetails.column\r\n },\r\n end: {\r\n offset: endPos,\r\n line: endPosDetails.line,\r\n column: endPosDetails.column\r\n }\r\n };\r\n }\r\n\r\n function peg$fail(expected) {\r\n if (peg$currPos < peg$maxFailPos) {\r\n return;\r\n }\r\n\r\n if (peg$currPos > peg$maxFailPos) {\r\n peg$maxFailPos = peg$currPos;\r\n peg$maxFailExpected = [];\r\n }\r\n\r\n peg$maxFailExpected.push(expected);\r\n }\r\n\r\n function peg$buildSimpleError(message, location) {\r\n return new peg$SyntaxError(message, null, null, location);\r\n }\r\n\r\n function peg$buildStructuredError(expected, found, location) {\r\n return new peg$SyntaxError(\r\n peg$SyntaxError.buildMessage(expected, found),\r\n expected,\r\n found,\r\n location\r\n );\r\n }\r\n\r\n function peg$parsechain() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n s2 = peg$parseatom();\r\n if (s2 !== peg$FAILED) {\r\n s3 = [];\r\n s4 = peg$parsebranch();\r\n while (s4 !== peg$FAILED) {\r\n s3.push(s4);\r\n s4 = peg$parsebranch();\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = [];\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n while (s5 !== peg$FAILED) {\r\n s4.push(s5);\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n s6 = peg$parsebranch();\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n s6 = peg$parsebranch();\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsechain();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = [];\r\n s9 = peg$parsebranch();\r\n while (s9 !== peg$FAILED) {\r\n s8.push(s9);\r\n s9 = peg$parsebranch();\r\n }\r\n if (s8 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c0(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebranch() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 40) {\r\n s2 = peg$c1;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c2);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parsebond();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = peg$parsechain();\r\n if (s4 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 41) {\r\n s5 = peg$c3;\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c4);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c5(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseatom() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseorganicsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsearomaticsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsebracketatom();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebond() {\r\n var s0, s1;\r\n s0 = peg$currPos;\r\n if (peg$c7.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n\r\n // Hack to resolve problem caused by:\r\n // O=C(N[C@@H](CC(O)=O)C(N[C@H](C1=CC=C(O)C=C1)C(N[C@@H](CC(O)=O)C(NCC(N[C@@H](C(N[C@@H]([C@H](C)CC(O)=O)C(N/C(C(O[C@H](C)[C@@H]2NC([C@H](CO)NC(C(O3)C3CCC)=O)=O)=O)=C\\\\\\\\C4=CNC5=C4C=CC=C5)=O)=O)[C@H](O)C(N)=O)=O)=O)=O)=O)[C@H](CC(O)=O)NC([C@@H](CC6=CNC7=C6C=CC=C7)NC2=O)=O\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n if (s1 === input.charAt(peg$currPos + 1)) {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n throw peg$buildSimpleError('The parser encountered a bond repetition.', peg$currPos + 1);\r\n }\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c8);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c9(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebracketatom() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 91) {\r\n s2 = peg$c10;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c11);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parseisotope();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c12) {\r\n s4 = peg$c12;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c13);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c14) {\r\n s4 = peg$c14;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c15);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsearomaticsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parseelementsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = peg$parsechiral();\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsehcount();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsecharge();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = peg$parseclass();\r\n if (s8 === peg$FAILED) {\r\n s8 = null;\r\n }\r\n if (s8 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 93) {\r\n s9 = peg$c16;\r\n peg$currPos++;\r\n } else {\r\n s9 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c17);\r\n }\r\n }\r\n if (s9 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8, s9];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c18(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseorganicsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 66) {\r\n s2 = peg$c19;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c20);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 114) {\r\n s3 = peg$c21;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c22);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 67) {\r\n s2 = peg$c23;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c24);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 108) {\r\n s3 = peg$c25;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c26);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c27.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c28);\r\n }\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c29(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsearomaticsymbol() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (peg$c30.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c31);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsewildcard() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 42) {\r\n s1 = peg$c32;\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c33);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c34(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseelementsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c35.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c36);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c37.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c38);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c39(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsering() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 37) {\r\n s2 = peg$c40;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c41);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c46(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsechiral() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s2 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s3 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c49) {\r\n s4 = peg$c49;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c50);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c53) {\r\n s4 = peg$c53;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c54);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c55) {\r\n s4 = peg$c55;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c56);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c57.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c58);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c59) {\r\n s4 = peg$c59;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c60);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c61) {\r\n s4 = peg$c61;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c62);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c63(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsecharge() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseposcharge();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsenegcharge();\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c64(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseposcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s2 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s3 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c67(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsenegcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s2 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s3 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c70(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsehcount() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 72) {\r\n s2 = peg$c71;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c72);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c73(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseclass() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 58) {\r\n s2 = peg$c74;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c75);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n if (peg$c76.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c77);\r\n }\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c78(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseisotope() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = null;\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c79(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n peg$result = peg$startRuleFunction();\r\n\r\n if (peg$result !== peg$FAILED && peg$currPos === input.length) {\r\n return peg$result;\r\n } else {\r\n if (peg$result !== peg$FAILED && peg$currPos < input.length) {\r\n peg$fail(peg$endExpectation());\r\n }\r\n\r\n throw peg$buildStructuredError(\r\n peg$maxFailExpected,\r\n peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,\r\n peg$maxFailPos < input.length ?\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) :\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n SyntaxError: peg$SyntaxError,\r\n parse: peg$parse\r\n };\r\n})();","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Vertex = require('./Vertex')\r\nconst RingConnection = require('./RingConnection')\r\n\r\n/** \r\n * A class representing a ring.\r\n * \r\n * @property {Number} id The id of this ring.\r\n * @property {Number[]} members An array containing the vertex ids of the ring members.\r\n * @property {Number[]} edges An array containing the edge ids of the edges between the ring members.\r\n * @property {Number[]} insiders An array containing the vertex ids of the vertices contained within the ring if it is a bridged ring.\r\n * @property {Number[]} neighbours An array containing the ids of neighbouring rings.\r\n * @property {Boolean} positioned A boolean indicating whether or not this ring has been positioned.\r\n * @property {Vector2} center The center of this ring.\r\n * @property {Ring[]} rings The rings contained within this ring if this ring is bridged.\r\n * @property {Boolean} isBridged A boolean whether or not this ring is bridged.\r\n * @property {Boolean} isPartOfBridged A boolean whether or not this ring is part of a bridge ring.\r\n * @property {Boolean} isSpiro A boolean whether or not this ring is part of a spiro.\r\n * @property {Boolean} isFused A boolean whether or not this ring is part of a fused ring.\r\n * @property {Number} centralAngle The central angle of this ring.\r\n * @property {Boolean} canFlip A boolean indicating whether or not this ring allows flipping of attached vertices to the inside of the ring.\r\n */\r\nclass Ring {\r\n /**\r\n * The constructor for the class Ring.\r\n *\r\n * @param {Number[]} members An array containing the vertex ids of the members of the ring to be created.\r\n */\r\n constructor(members) {\r\n this.id = null;\r\n this.members = members;\r\n this.edges = [];\r\n this.insiders = [];\r\n this.neighbours = [];\r\n this.positioned = false;\r\n this.center = new Vector2(0, 0);\r\n this.rings = [];\r\n this.isBridged = false;\r\n this.isPartOfBridged = false;\r\n this.isSpiro = false;\r\n this.isFused = false;\r\n this.centralAngle = 0.0;\r\n this.canFlip = true;\r\n }\r\n \r\n /**\r\n * Clones this ring and returns the clone.\r\n *\r\n * @returns {Ring} A clone of this ring.\r\n */\r\n clone() {\r\n let clone = new Ring(this.members);\r\n\r\n clone.id = this.id;\r\n clone.insiders = ArrayHelper.clone(this.insiders);\r\n clone.neighbours = ArrayHelper.clone(this.neighbours);\r\n clone.positioned = this.positioned;\r\n clone.center = this.center.clone();\r\n clone.rings = ArrayHelper.clone(this.rings);\r\n clone.isBridged = this.isBridged;\r\n clone.isPartOfBridged = this.isPartOfBridged;\r\n clone.isSpiro = this.isSpiro;\r\n clone.isFused = this.isFused;\r\n clone.centralAngle = this.centralAngle;\r\n clone.canFlip = this.canFlip;\r\n\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns the size (number of members) of this ring.\r\n *\r\n * @returns {Number} The size (number of members) of this ring.\r\n */\r\n getSize() {\r\n return this.members.length;\r\n }\r\n\r\n /**\r\n * Gets the polygon representation (an array of the ring-members positional vectors) of this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices representing the current molecule.\r\n * @returns {Vector2[]} An array of the positional vectors of the ring members.\r\n */\r\n getPolygon(vertices) {\r\n let polygon = [];\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n polygon.push(vertices[this.members[i]].position);\r\n }\r\n\r\n return polygon;\r\n }\r\n\r\n /**\r\n * Returns the angle of this ring in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n return Math.PI - this.centralAngle;\r\n }\r\n\r\n /**\r\n * Loops over the members of this ring from a given start position in a direction opposite to the vertex id passed as the previousId.\r\n *\r\n * @param {Vertex[]} vertices The vertices associated with the current molecule.\r\n * @param {Function} callback A callback with the current vertex id as a parameter.\r\n * @param {Number} startVertexId The vertex id of the start vertex.\r\n * @param {Number} previousVertexId The vertex id of the previous vertex (the loop calling the callback function will run in the opposite direction of this vertex).\r\n */\r\n eachMember(vertices, callback, startVertexId, previousVertexId) {\r\n startVertexId = startVertexId || startVertexId === 0 ? startVertexId : this.members[0];\r\n let current = startVertexId;\r\n let max = 0;\r\n\r\n while (current != null && max < 100) {\r\n let prev = current;\r\n \r\n callback(prev);\r\n current = vertices[current].getNextInRing(vertices, this.id, previousVertexId);\r\n previousVertexId = prev;\r\n \r\n // Stop while loop when arriving back at the start vertex\r\n if (current == startVertexId) {\r\n current = null;\r\n }\r\n\r\n max++;\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array containing the neighbouring rings of this ring ordered by ring size.\r\n *\r\n * @param {RingConnection[]} ringConnections An array of ring connections associated with the current molecule.\r\n * @returns {Object[]} An array of neighbouring rings sorted by ring size. Example: { n: 5, neighbour: 1 }.\r\n */\r\n getOrderedNeighbours(ringConnections) {\r\n let orderedNeighbours = Array(this.neighbours.length);\r\n \r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n let vertices = RingConnection.getVertices(ringConnections, this.id, this.neighbours[i]);\r\n \r\n orderedNeighbours[i] = {\r\n n: vertices.length,\r\n neighbour: this.neighbours[i]\r\n };\r\n }\r\n\r\n orderedNeighbours.sort(function (a, b) {\r\n // Sort highest to lowest\r\n return b.n - a.n;\r\n });\r\n\r\n return orderedNeighbours;\r\n }\r\n\r\n /**\r\n * Check whether this ring is an implicitly defined benzene-like (e.g. C1=CC=CC=C1) with 6 members and 3 double bonds.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring is an implicitly defined benzene-like.\r\n */\r\n isBenzeneLike(vertices) {\r\n let db = this.getDoubleBondCount(vertices);\r\n let length = this.members.length;\r\n\r\n return db === 3 && length === 6 ||\r\n db === 2 && length === 5 ;\r\n }\r\n\r\n /**\r\n * Get the number of double bonds inside this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Number} The number of double bonds inside this ring.\r\n */\r\n getDoubleBondCount(vertices) {\r\n let doubleBondCount = 0;\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n let atom = vertices[this.members[i]].value;\r\n\r\n if (atom.bondType === '=' || atom.branchBond === '=') {\r\n doubleBondCount++;\r\n }\r\n }\r\n\r\n return doubleBondCount;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring contains a member with a given vertex id.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not this ring contains a member with the given vertex id.\r\n */\r\n contains(vertexId) {\r\n for (let i = 0; i < this.members.length; i++) {\r\n if (this.members[i] == vertexId) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n\r\nmodule.exports = Ring;","//@ts-check\r\nconst Vertex = require('./Vertex')\r\nconst Ring = require('./Ring')\r\n\r\n/** \r\n * A class representing a ring connection.\r\n * \r\n * @property {Number} id The id of this ring connection.\r\n * @property {Number} firstRingId A ring id.\r\n * @property {Number} secondRingId A ring id.\r\n * @property {Set} vertices A set containing the vertex ids participating in the ring connection.\r\n */\r\nclass RingConnection {\r\n /**\r\n * The constructor for the class RingConnection.\r\n *\r\n * @param {Ring} firstRing A ring.\r\n * @param {Ring} secondRing A ring.\r\n */\r\n constructor(firstRing, secondRing) {\r\n this.id = null;\r\n this.firstRingId = firstRing.id;\r\n this.secondRingId = secondRing.id;\r\n this.vertices = new Set();\r\n\r\n for (var m = 0; m < firstRing.members.length; m++) {\r\n let c = firstRing.members[m];\r\n\r\n for (let n = 0; n < secondRing.members.length; n++) {\r\n let d = secondRing.members[n];\r\n\r\n if (c === d) {\r\n this.addVertex(c);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adding a vertex to the ring connection.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n */\r\n addVertex(vertexId) {\r\n this.vertices.add(vertexId);\r\n }\r\n\r\n /**\r\n * Update the ring id of this ring connection that is not the ring id supplied as the second argument.\r\n *\r\n * @param {Number} ringId A ring id. The new ring id to be set.\r\n * @param {Number} otherRingId A ring id. The id that is NOT to be updated.\r\n */\r\n updateOther(ringId, otherRingId) {\r\n if (this.firstRingId === otherRingId) {\r\n this.secondRingId = ringId;\r\n } else {\r\n this.firstRingId = ringId;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.\r\n * \r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.\r\n */\r\n containsRing(ringId) {\r\n return this.firstRingId === ringId || this.secondRingId === ringId;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring connection is a bridge in a bridged ring.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.\r\n */\r\n isBridge(vertices) {\r\n if (this.vertices.size > 2) {\r\n return true;\r\n }\r\n\r\n for (let vertexId of this.vertices) {\r\n if(vertices[vertexId].value.rings.length > 2) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two rings are connected by a bridged bond.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.\r\n */\r\n static isBridge(ringConnections, vertices, firstRingId, secondRingId) {\r\n let ringConnection = null;\r\n \r\n for (let i = 0; i < ringConnections.length; i++) {\r\n ringConnection = ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return ringConnection.isBridge(vertices);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Retruns the neighbouring rings of a given ring.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array of ring ids of neighbouring rings.\r\n */\r\n static getNeighbours(ringConnections, ringId) {\r\n let neighbours = [];\r\n\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n \r\n if (ringConnection.firstRingId === ringId) {\r\n neighbours.push(ringConnection.secondRingId);\r\n } else if (ringConnection.secondRingId === ringId) {\r\n neighbours.push(ringConnection.firstRingId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Returns an array of vertex ids associated with a given ring connection.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Number[]} An array of vertex ids associated with the ring connection.\r\n */\r\n static getVertices(ringConnections, firstRingId, secondRingId) {\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return [...ringConnection.vertices];\r\n }\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = RingConnection","//@ts-check\r\nconst Graph = require('./Graph')\r\n\r\n/** A class encapsulating the functionality to find the smallest set of smallest rings in a graph. */\r\nclass SSSR {\r\n /**\r\n * Returns an array containing arrays, each representing a ring from the smallest set of smallest rings in the graph.\r\n * \r\n * @param {Graph} graph A Graph object.\r\n * @param {Boolean} [experimental=false] Whether or not to use experimental SSSR.\r\n * @returns {Array[]} An array containing arrays, each representing a ring from the smallest set of smallest rings in the group.\r\n */\r\n static getRings(graph, experimental=false) {\r\n let adjacencyMatrix = graph.getComponentsAdjacencyMatrix();\r\n if (adjacencyMatrix.length === 0) {\r\n return null;\r\n }\r\n\r\n let connectedComponents = Graph.getConnectedComponents(adjacencyMatrix);\r\n let rings = Array();\r\n\r\n for (var i = 0; i < connectedComponents.length; i++) {\r\n let connectedComponent = connectedComponents[i];\r\n let ccAdjacencyMatrix = graph.getSubgraphAdjacencyMatrix([...connectedComponent]);\r\n\r\n let arrBondCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n let arrRingCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n arrRingCount[j] = 0;\r\n arrBondCount[j] = 0;\r\n\r\n for (var k = 0; k < ccAdjacencyMatrix[j].length; k++) {\r\n arrBondCount[j] += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n // Get the edge number and the theoretical number of rings in SSSR\r\n let nEdges = 0;\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n for (var k = j + 1; k < ccAdjacencyMatrix.length; k++) {\r\n nEdges += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n let nSssr = nEdges - ccAdjacencyMatrix.length + 1;\r\n\r\n // console.log(nEdges, ccAdjacencyMatrix.length, nSssr);\r\n // console.log(SSSR.getEdgeList(ccAdjacencyMatrix));\r\n // console.log(ccAdjacencyMatrix);\r\n\r\n // If all vertices have 3 incident edges, calculate with different formula (see Euler)\r\n let allThree = true;\r\n for (var j = 0; j < arrBondCount.length; j++) {\r\n if (arrBondCount[j] !== 3) {\r\n allThree = false;\r\n }\r\n }\r\n\r\n if (allThree) {\r\n nSssr = 2.0 + nEdges - ccAdjacencyMatrix.length;\r\n }\r\n\r\n // All vertices are part of one ring if theres only one ring.\r\n if (nSssr === 1) {\r\n rings.push([...connectedComponent]);\r\n continue;\r\n }\r\n \r\n if (experimental) {\r\n nSssr = 999;\r\n }\r\n\r\n let { d, pe, pe_prime } = SSSR.getPathIncludedDistanceMatrices(ccAdjacencyMatrix);\r\n let c = SSSR.getRingCandidates(d, pe, pe_prime);\r\n let sssr = SSSR.getSSSR(c, d, ccAdjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nSssr);\r\n\r\n for (var j = 0; j < sssr.length; j++) {\r\n let ring = Array(sssr[j].size);\r\n let index = 0;\r\n\r\n for (let val of sssr[j]) {\r\n // Get the original id of the vertex back\r\n ring[index++] = connectedComponent[val];\r\n }\r\n\r\n rings.push(ring);\r\n }\r\n }\r\n \r\n\r\n // So, for some reason, this would return three rings for C1CCCC2CC1CCCC2, which is wrong\r\n // As I don't have time to fix this properly, it will stay in. I'm sorry next person who works\r\n // on it. At that point it might be best to reimplement the whole SSSR thing...\r\n return rings;\r\n }\r\n\r\n /**\r\n * Creates a printable string from a matrix (2D array).\r\n * \r\n * @param {Array[]} matrix A 2D array.\r\n * @returns {String} A string representing the matrix.\r\n */\r\n static matrixToString(matrix) {\r\n let str = '';\r\n\r\n for (var i = 0; i < matrix.length; i++) {\r\n for (var j = 0; j < matrix[i].length; j++) {\r\n str += matrix[i][j] + ' ';\r\n }\r\n\r\n str += '\\n';\r\n }\r\n\r\n return str;\r\n }\r\n\r\n /**\r\n * Returnes the two path-included distance matrices used to find the sssr.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Object} The path-included distance matrices. { p1, p2 }\r\n */\r\n static getPathIncludedDistanceMatrices(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let d = Array(length);\r\n let pe = Array(length);\r\n let pe_prime = Array(length);\r\n var l = 0;\r\n var m = 0;\r\n var n = 0;\r\n\r\n var i = length;\r\n while (i--) {\r\n d[i] = Array(length);\r\n pe[i] = Array(length);\r\n pe_prime[i] = Array(length);\r\n\r\n var j = length;\r\n while (j--) {\r\n d[i][j] = (i === j || adjacencyMatrix[i][j] === 1) ? adjacencyMatrix[i][j] : Number.POSITIVE_INFINITY;\r\n\r\n if (d[i][j] === 1) {\r\n pe[i][j] = [[[i, j]]];\r\n } else {\r\n pe[i][j] = Array();\r\n }\r\n\r\n pe_prime[i][j] = Array();\r\n }\r\n }\r\n\r\n var k = length;\r\n var j;\r\n while (k--) {\r\n i = length;\r\n while (i--) {\r\n j = length;\r\n while (j--) {\r\n const previousPathLength = d[i][j];\r\n const newPathLength = d[i][k] + d[k][j];\r\n\r\n if (previousPathLength > newPathLength) {\r\n var l, m, n;\r\n if (previousPathLength === newPathLength + 1) {\r\n pe_prime[i][j] = [pe[i][j].length];\r\n l = pe[i][j].length\r\n while (l--) {\r\n pe_prime[i][j][l] = [pe[i][j][l].length];\r\n m = pe[i][j][l].length\r\n while (m--) {\r\n pe_prime[i][j][l][m] = [pe[i][j][l][m].length];\r\n n = pe[i][j][l][m].length;\r\n while (n--) {\r\n pe_prime[i][j][l][m][n] = [pe[i][j][l][m][0], pe[i][j][l][m][1]];\r\n }\r\n }\r\n }\r\n } else {\r\n pe_prime[i][j] = Array();\r\n }\r\n\r\n d[i][j] = newPathLength;\r\n\r\n pe[i][j] = [[]];\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[k][j][0][l]);\r\n }\r\n } else if (previousPathLength === newPathLength) {\r\n if (pe[i][k].length && pe[k][j].length) {\r\n var l;\r\n if (pe[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j][0] = tmp\r\n }\r\n }\r\n } else if (previousPathLength === newPathLength - 1) {\r\n var l;\r\n if (pe_prime[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j][0] = tmp;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n d: d,\r\n pe: pe,\r\n pe_prime: pe_prime\r\n };\r\n }\r\n\r\n /**\r\n * Get the ring candidates from the path-included distance matrices.\r\n * \r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @returns {Array[]} The ring candidates.\r\n */\r\n static getRingCandidates(d, pe, pe_prime) {\r\n let length = d.length;\r\n let candidates = Array();\r\n let c = 0;\r\n\r\n for (let i = 0; i < length; i++) {\r\n for (let j = 0; j < length; j++) {\r\n if (d[i][j] === 0 || (pe[i][j].length === 1 && pe_prime[i][j] === 0)) {\r\n continue;\r\n } else {\r\n // c is the number of vertices in the cycle.\r\n if (pe_prime[i][j].length !== 0) {\r\n c = 2 * (d[i][j] + 0.5);\r\n } else {\r\n c = 2 * d[i][j];\r\n }\r\n\r\n if (c !== Infinity) {\r\n candidates.push([c, pe[i][j], pe_prime[i][j]]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Candidates have to be sorted by c\r\n candidates.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n\r\n return candidates;\r\n }\r\n\r\n /**\r\n * Searches the candidates for the smallest set of smallest rings.\r\n * \r\n * @param {Array[]} c The candidates.\r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @param {Number} nsssr The theoretical number of rings in the graph.\r\n * @returns {Set[]} The smallest set of smallest rings.\r\n */\r\n static getSSSR(c, d, adjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nsssr) {\r\n let cSssr = Array();\r\n let allBonds = Array();\r\n\r\n for (let i = 0; i < c.length; i++) {\r\n if (c[i][0] % 2 !== 0) {\r\n for (let j = 0; j < c[i][2].length; j++) {\r\n let bonds = c[i][1][0].concat(c[i][2][j]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n } else {\r\n for (let j = 0; j < c[i][1].length - 1; j++) {\r\n let bonds = c[i][1][j].concat(c[i][1][j + 1]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return cSssr;\r\n }\r\n\r\n /**\r\n * Returns the number of edges in a graph defined by an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of edges in the graph defined by the adjacency matrix.\r\n */\r\n static getEdgeCount(adjacencyMatrix) {\r\n let edgeCount = 0;\r\n let length = adjacencyMatrix.length;\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeCount++;\r\n }\r\n }\r\n }\r\n\r\n return edgeCount;\r\n }\r\n\r\n /**\r\n * Returns an edge list constructed form an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Array[]} An edge list. E.g. [ [ 0, 1 ], ..., [ 16, 2 ] ]\r\n */\r\n static getEdgeList(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let edgeList = Array();\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeList.push([i, j]);\r\n }\r\n }\r\n }\r\n\r\n return edgeList;\r\n }\r\n\r\n /**\r\n * Return a set of vertex indices contained in an array of bonds.\r\n * \r\n * @param {Array} bonds An array of bonds. A bond is defined as [ sourceVertexId, targetVertexId ].\r\n * @returns {Set} An array of vertices.\r\n */\r\n static bondsToAtoms(bonds) {\r\n let atoms = new Set();\r\n\r\n var i = bonds.length;\r\n while (i--) {\r\n atoms.add(bonds[i][0]);\r\n atoms.add(bonds[i][1]);\r\n }\r\n return atoms;\r\n }\r\n\r\n /**\r\n * Returns the number of bonds within a set of atoms.\r\n * \r\n * @param {Set} atoms An array of atom ids.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of bonds in a set of atoms.\r\n */\r\n static getBondCount(atoms, adjacencyMatrix) {\r\n let count = 0;\r\n for (let u of atoms) {\r\n for (let v of atoms) {\r\n if (u === v) {\r\n continue;\r\n }\r\n count += adjacencyMatrix[u][v]\r\n }\r\n }\r\n\r\n return count / 2;\r\n }\r\n\r\n /**\r\n * Checks whether or not a given path already exists in an array of paths.\r\n * \r\n * @param {Set[]} pathSets An array of sets each representing a path.\r\n * @param {Set} pathSet A set representing a path.\r\n * @param {Array[]} bonds The bonds associated with the current path.\r\n * @param {Array[]} allBonds All bonds currently associated with rings in the SSSR set.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @returns {Boolean} A boolean indicating whether or not a give path is contained within a set.\r\n */\r\n static pathSetsContain(pathSets, pathSet, bonds, allBonds, arrBondCount, arrRingCount) {\r\n var i = pathSets.length;\r\n while (i--) {\r\n if (SSSR.isSupersetOf(pathSet, pathSets[i])) {\r\n return true;\r\n }\r\n\r\n if (pathSets[i].size !== pathSet.size) {\r\n continue;\r\n }\r\n\r\n if (SSSR.areSetsEqual(pathSets[i], pathSet)) {\r\n return true;\r\n }\r\n }\r\n\r\n // Check if the edges from the candidate are already all contained within the paths of the set of paths.\r\n // TODO: For some reason, this does not replace the isSupersetOf method above -> why?\r\n let count = 0;\r\n let allContained = false;\r\n i = bonds.length;\r\n while (i--) {\r\n var j = allBonds.length;\r\n while (j--) {\r\n if (bonds[i][0] === allBonds[j][0] && bonds[i][1] === allBonds[j][1] ||\r\n bonds[i][1] === allBonds[j][0] && bonds[i][0] === allBonds[j][1]) {\r\n count++;\r\n }\r\n\r\n if (count === bonds.length) {\r\n allContained = true;\r\n }\r\n }\r\n }\r\n\r\n // If all the bonds and thus vertices are already contained within other rings\r\n // check if there's one vertex with ringCount < bondCount\r\n let specialCase = false;\r\n if (allContained) {\r\n for (let element of pathSet) {\r\n if (arrRingCount[element] < arrBondCount[element]) {\r\n specialCase = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (allContained && !specialCase) {\r\n return true;\r\n }\r\n\r\n // Update the ring counts for the vertices\r\n for (let element of pathSet) {\r\n arrRingCount[element]++;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two sets are equal (contain the same elements).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not the two sets are equal.\r\n */\r\n static areSetsEqual(setA, setB) {\r\n if (setA.size !== setB.size) {\r\n return false;\r\n }\r\n\r\n for (let element of setA) {\r\n if (!setB.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Checks whether or not a set (setA) is a superset of another set (setB).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not setB is a superset of setA.\r\n */\r\n static isSupersetOf(setA, setB) {\r\n for (var element of setB) {\r\n if (!setA.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\nmodule.exports = SSSR;","//@ts-check\r\n\r\nclass SequenceType {\r\n\r\n static get VALUES() {\r\n return {\r\n LINEAR: \"linear\",\r\n CYCLIC: \"cyclic\",\r\n BRANCH: \"branched\",\r\n BRANCH_CYCLIC: \"branch-cyclic\",\r\n LINEAR_POLYKETIDE: \"linear-polyketide\",\r\n CYCLIC_POLYKETIDE: \"cyclic-polyketide\",\r\n OTHER: \"other\",\r\n }\r\n }\r\n\r\n static getTypeFromValues(isCyclic, isBranch, isOther) {\r\n if (isOther) { return this.VALUES.OTHER;}\r\n if (!isCyclic && !isBranch) {\r\n return this.VALUES.LINEAR;\r\n } else if(isCyclic && !isBranch) {\r\n return this.VALUES.CYCLIC;\r\n } else if (!isCyclic) {\r\n return this.VALUES.BRANCH;\r\n } else {\r\n return this.VALUES.BRANCH_CYCLIC;\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = SequenceType;\r\n","//@ts-check\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst VertexState = require('./VertexState');\r\nconst Neighbour = require('./Neighbour');\r\nconst Direction = require('./Direction');\r\n\r\nclass SmallGraph {\r\n\r\n constructor() {\r\n this._nodes = [];\r\n this.isOther = false;\r\n this._branch = false;\r\n this.isCyclic = false;\r\n this.isBranched = false;\r\n this.sequenceType = SequenceType.VALUES.LINEAR;\r\n this._nodeOnRing = null;\r\n }\r\n\r\n addVertex(node) {\r\n this._nodes.push(node);\r\n }\r\n\r\n addNeighbour(nodeId, neighbour, direction) {\r\n this._nodes[nodeId].addNeighbour(new Neighbour(neighbour, direction));\r\n }\r\n\r\n dfsInitialization() {\r\n this._nodes.forEach(e => e.vertexState = VertexState.VALUES.NOT_FOUND);\r\n }\r\n\r\n getSourceNode() {\r\n let ends = [];\r\n for (let index = 0; index < this._nodes.length; ++index) {\r\n if (this._nodes[index].neighbours.length === 1) {\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.C) {\r\n return this._nodes[index];\r\n }\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.POLYKETIDE) {\r\n return this._nodes[index];\r\n }\r\n ends.push(this._nodes[index]);\r\n }\r\n }\r\n if (ends.length > 0) {\r\n return ends[0];\r\n }\r\n return null;\r\n }\r\n\r\n oneCyclic() {\r\n if (this._nodes.length === 0) {\r\n return false;\r\n }\r\n this.dfsInitialization();\r\n this.isCyclic = false;\r\n if (this._nodes.length === 2 && this._nodes[0].neighbours.length === 2 && this._nodes[1].neighbours.length === 2) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = this._nodes[0];\r\n } else {\r\n this.dfsCyclic(this._nodes[0], -1);\r\n }\r\n }\r\n\r\n dfsCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = vertex;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.neighbours.length; ++i) {\r\n if (vertexFromId !== vertex.neighbours[i].neighbour) {\r\n this.dfsCyclic(this._nodes[vertex.neighbours[i].neighbour], vertex.id);\r\n }\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSequenceStart() {\r\n if (this._nodes.length === 0) {\r\n return;\r\n }\r\n this.dfsInitialization();\r\n this.sequence = \"\";\r\n if (this.isCyclic) {\r\n this.findRing(this._nodeOnRing);\r\n this.dfsSequenceCyclic(this._nodeOnRing);\r\n } else {\r\n let sourceNode = this.getSourceNode();\r\n if (sourceNode !== null) {\r\n this.dfsSequence(this.getSourceNode(), -1);\r\n } else {\r\n this.sequenceType = 'other';\r\n this.isOther = true;\r\n return;\r\n }\r\n }\r\n if (this.sequence.charAt(this.sequence.length - 1) === '-') {\r\n this.sequence = this.sequence.substr(0, this.sequence.length - 1);\r\n }\r\n this.sequenceType = SequenceType.getTypeFromValues(this.isCyclic, this.isBranched, this.isOther);\r\n }\r\n\r\n arrayContainsTimes(array, searchValue, times) {\r\n let cnt = 0;\r\n for (let index = 0; index < array.length; ++index) {\r\n if (array[index].neighbour === searchValue) {\r\n cnt++;\r\n if (cnt === times) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n findRing(start) {\r\n let queue = [];\r\n let firstPath = [start.id];\r\n let firstPass = true;\r\n queue.push(firstPath);\r\n while (queue.length !== 0) {\r\n let path = queue.pop();\r\n let last = path[path.length - 1];\r\n let node = this._nodes[last];\r\n if (node.id === start.id && !firstPass) {\r\n if (path.length === 3 && path[0] === path[2] && !this.arrayContainsTimes(this._nodes[path[0]].neighbours, path[1], 2)) {\r\n continue;\r\n }\r\n path.forEach(v => this._nodes[v].onRing = true);\r\n continue;\r\n }\r\n node.neighbours.forEach(\r\n neighbour => {\r\n if (!path.some(e => e === neighbour.neighbour) || neighbour.neighbour === start.id) {\r\n let newPath = [...path];\r\n newPath.push(neighbour.neighbour);\r\n queue.push(newPath);\r\n }\r\n }\r\n );\r\n firstPass = false;\r\n }\r\n }\r\n\r\n sortByRingPreference(array) {\r\n let sortedArray = [...array];\r\n sortedArray.sort((a, b) => {\r\n if (this._nodes[a.neighbour].onRing === this._nodes[b.neighbour].onRing) {\r\n if (a.direction > b.direction) {\r\n return -1;\r\n } else if (a.direction < b.direction) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n } else if (this._nodes[a.neighbour].onRing) {\r\n return 1;\r\n } else {\r\n return -1;\r\n }\r\n });\r\n return sortedArray;\r\n }\r\n\r\n dfsSequenceCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n let sortedNeighbours = this.sortByRingPreference(vertex.neighbours);\r\n for (let index = 0; index < sortedNeighbours.length; ++index) {\r\n if (vertexFromId === sortedNeighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequenceCyclic(this._nodes[sortedNeighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n printVertex(vertexId) {\r\n this.sequence += `[${vertexId}]`;\r\n }\r\n\r\n printDash() {\r\n if (']' === this.sequence[this.sequence.length - 1]) {\r\n this.sequence += '-';\r\n }\r\n }\r\n\r\n printLeftBrace(vertex) {\r\n if (vertex.neighbours.length > 2) {\r\n if (this.isBranched) {\r\n this.isOther = true;\r\n }\r\n this.sequence += '\\\\(';\r\n this._branch = true;\r\n this.isBranched = true;\r\n }\r\n }\r\n\r\n printRightBrace() {\r\n if (this._branch) {\r\n this.sequence += '\\\\)';\r\n this._branch = false;\r\n }\r\n }\r\n\r\n dfsSequence(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n for (let index = 0; index < vertex.neighbours.length; ++index) {\r\n if (vertexFromId === vertex.neighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequence(this._nodes[vertex.neighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n}\r\n\r\nmodule.exports = SmallGraph;\r\n","// we use the drawer to do all the preprocessing. then we take over the drawing\r\n// portion to output to svg\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Atom = require('./Atom');\r\nconst Drawer = require('./Drawer');\r\nconst Graph = require('./Graph');\r\nconst Line = require('./Line');\r\nconst SvgWrapper = require('./SvgWrapper');\r\nconst ThemeManager = require('./ThemeManager');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgDrawer {\r\n constructor(options) {\r\n this.preprocessor = new Drawer(options);\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to an svg element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML svg element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n\r\n * @returns {Oject} The dimensions of the drawing in { width, height }\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n let preprocessor = this.preprocessor;\r\n\r\n preprocessor.initDraw(data, themeName, infoOnly);\r\n\r\n if (!infoOnly) {\r\n this.themeManager = new ThemeManager(this.preprocessor.opts.themes, themeName);\r\n this.svgWrapper = new SvgWrapper(this.themeManager, target, this.preprocessor.opts);\r\n }\r\n\r\n preprocessor.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.svgWrapper.determineDimensions(preprocessor.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(preprocessor.opts.debug);\r\n this.drawVertices(preprocessor.opts.debug);\r\n\r\n if (preprocessor.opts.debug) {\r\n console.log(preprocessor.graph);\r\n console.log(preprocessor.rings);\r\n console.log(preprocessor.ringConnections);\r\n }\r\n\r\n return this.svgWrapper.constructSvg();\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let preprocessor = this.preprocessor,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n drawn = Array(this.preprocessor.graph.edges.length);\r\n\r\n drawn.fill(false);\r\n\r\n graph.traverseBF(0, vertex => {\r\n let edges = graph.getEdges(vertex.id);\r\n for (var i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n this.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let ring = rings[i];\r\n\r\n if (preprocessor.isRingAromatic(ring)) {\r\n this.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bond.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n svgWrapper = this.svgWrapper,\r\n edge = preprocessor.graph.edges[edgeId],\r\n vertexA = preprocessor.graph.vertices[edge.sourceId],\r\n vertexB = preprocessor.graph.vertices[edge.targetId],\r\n elementA = vertexA.value.element,\r\n elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && preprocessor.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position,\r\n b = vertexB.position,\r\n normals = preprocessor.getEdgeNormals(edge),\r\n // Create a point on each side of the line\r\n sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || preprocessor.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && preprocessor.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = preprocessor.areVerticesInSameRing(vertexA, vertexB);\r\n let s = preprocessor.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(opts.bondSpacing);\r\n normals[1].multiplyScalar(opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line = null;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n }\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n // preprocessor.canvasWrapper.drawLine(line, true);\r\n svgWrapper.drawLine(line, true);\r\n } else {\r\n // preprocessor.canvasWrapper.drawLine(line);\r\n svgWrapper.drawLine(line);\r\n }\r\n\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((edge.center || vertexA.isTerminal() && vertexB.isTerminal()) ||\r\n (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1)) {\r\n this.multiplyNormals(normals, opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB),\r\n lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n } else if ((s.sideCount[0] > s.sideCount[1]) ||\r\n (s.totalSideCount[0] > s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((s.sideCount[0] < s.sideCount[1]) ||\r\n (s.totalSideCount[0] <= s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n svgWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else if (edge.wedge === 'down') {\r\n svgWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else {\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n svgWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n svgWrapper = this.svgWrapper;\r\n\r\n var i = graph.vertices.length;\r\n for (var i = 0; i < graph.vertices.length; i++) {\r\n let vertex = graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(graph.vertices);\r\n let isTerminal = opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (opts.atomVisualization === 'allballs') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || graph.vertices.length === 1) {\r\n if (opts.atomVisualization === 'default') {\r\n svgWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (opts.atomVisualization === 'balls') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = graph.vertices[vertex.neighbours[0]].position;\r\n let b = graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n svgWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (opts.debug) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let center = rings[i].center;\r\n svgWrapper.drawDebugPoint(center.x, center.y, 'r: ' + rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.preprocessor.getTotalOverlapScore();\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n return this.preprocessor.getMolecularFormula();\r\n }\r\n\r\n /**\r\n * @param {Array} normals list of normals to multiply\r\n * @param {Number} spacing value to multiply normals by\r\n */\r\n multiplyNormals(normals, spacing) {\r\n normals[0].multiplyScalar(spacing);\r\n normals[1].multiplyScalar(spacing);\r\n }\r\n}\r\n\r\nmodule.exports = SvgDrawer;","const {\r\n getChargeText\r\n} = require('./UtilityFunctions');\r\n\r\nconst Line = require('./Line');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgWrapper {\r\n constructor(themeManager, target, options) {\r\n this.svg = document.getElementById(target);\r\n this.opts = options;\r\n this.gradientId = 0;\r\n\r\n // maintain a list of line elements and their corresponding gradients\r\n // maintain a list of vertex elements\r\n this.paths = [];\r\n this.vertices = [];\r\n this.gradients = [];\r\n\r\n // maintain the offset for drawing purposes\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n // maintain the dimensions\r\n this.drawingWidth = 0;\r\n this.drawingHeight = 0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // for managing color schemes\r\n this.themeManager = themeManager;\r\n\r\n // create the mask\r\n this.maskElements = [];\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\r\n mask.setAttributeNS(null, 'x', 0);\r\n mask.setAttributeNS(null, 'y', 0);\r\n mask.setAttributeNS(null, 'width', '100%');\r\n mask.setAttributeNS(null, 'height', '100%');\r\n mask.setAttributeNS(null, 'fill', 'white');\r\n\r\n this.maskElements.push(mask);\r\n\r\n // clear the svg element\r\n while (this.svg.firstChild) {\r\n this.svg.removeChild(this.svg.firstChild);\r\n }\r\n }\r\n\r\n constructSvg() {\r\n // TODO: add the defs element to put gradients in\r\n let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'),\r\n masks = document.createElementNS('http://www.w3.org/2000/svg', 'mask'),\r\n style = document.createElementNS('http://www.w3.org/2000/svg', 'style'),\r\n paths = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n vertices = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n pathChildNodes = this.paths;\r\n\r\n // give the mask an id\r\n masks.setAttributeNS(null, 'id', 'text-mask');\r\n\r\n // create the css styles\r\n style.appendChild(document.createTextNode(`\r\n .element {\r\n font: ${this.opts.fontSizeLarge}pt Helvetica, Arial, sans-serif;\r\n alignment-baseline: 'middle';\r\n }\r\n .sub {\r\n font: ${this.opts.fontSizeSmall}pt Helvetica, Arial, sans-serif;\r\n }\r\n `));\r\n\r\n for (let path of pathChildNodes) {\r\n paths.appendChild(path);\r\n }\r\n for (let vertex of this.vertices) {\r\n vertices.appendChild(vertex);\r\n }\r\n for (let mask of this.maskElements) {\r\n masks.appendChild(mask);\r\n }\r\n for (let gradient of this.gradients) {\r\n defs.appendChild(gradient);\r\n }\r\n\r\n paths.setAttributeNS(null, 'mask', 'url(#text-mask)');\r\n\r\n if (this.svg) {\r\n this.svg.appendChild(defs);\r\n this.svg.appendChild(masks);\r\n this.svg.appendChild(style);\r\n this.svg.appendChild(paths);\r\n this.svg.appendChild(vertices);\r\n return this.svg;\r\n } else {\r\n let container = document.createElementNS('http://www.w3.org/2000/svg', 'g');\r\n container.appendChild(defs);\r\n container.appendChild(masks);\r\n container.appendChild(style);\r\n container.appendChild(paths);\r\n container.appendChild(vertices);\r\n return container;\r\n }\r\n }\r\n\r\n /**\r\n * Create a linear gradient to apply to a line\r\n *\r\n * @param {Line} line the line to apply the gradiation to.\r\n */\r\n createGradient(line) {\r\n // create the gradient and add it\r\n let gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient'),\r\n gradientUrl = `line-${this.gradientId++}`,\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n gradient.setAttributeNS(null, 'id', gradientUrl);\r\n gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\r\n gradient.setAttributeNS(null, 'x1', fromX);\r\n gradient.setAttributeNS(null, 'y1', fromY);\r\n gradient.setAttributeNS(null, 'x2', toX);\r\n gradient.setAttributeNS(null, 'y2', toY);\r\n\r\n let firstStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n firstStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getLeftElement()) || this.themeManager.getColor('C'));\r\n firstStop.setAttributeNS(null, 'offset', '20%');\r\n\r\n let secondStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n secondStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getRightElement() || this.themeManager.getColor('C')));\r\n secondStop.setAttributeNS(null, 'offset', '100%');\r\n\r\n gradient.appendChild(firstStop);\r\n gradient.appendChild(secondStop);\r\n\r\n this.gradients.push(gradient);\r\n\r\n return gradientUrl;\r\n }\r\n\r\n /**\r\n * Create a tspan element for sub or super scripts that styles the text\r\n * appropriately as one of those text types.\r\n *\r\n * @param {String} text the actual text\r\n * @param {String} shift the type of text, either 'sub', or 'super'\r\n */\r\n createSubSuperScripts(text, shift) {\r\n let elem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n elem.setAttributeNS(null, 'baseline-shift', shift);\r\n elem.appendChild(document.createTextNode(text));\r\n elem.setAttributeNS(null, 'class', 'sub');\r\n\r\n return elem;\r\n }\r\n\r\n /**\r\n * Determine drawing dimensiosn based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n determineDimensions(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n let padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n let scaleX = this.svg.clientWidth / this.drawingWidth;\r\n let scaleY = this.svg.clientHeight / this.drawingHeight;\r\n\r\n let scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n let viewBoxDim = Math.round(this.drawingWidth > this.drawingHeight ? this.drawingWidth : this.drawingHeight);\r\n\r\n this.svg.setAttributeNS(null, 'viewBox', `0 0 ${viewBoxDim} ${viewBoxDim}`);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.svg.clientHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.svg.clientWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Draw an svg ellipse as a ball.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n ball.setAttributeNS(null, 'cx', x + this.offsetX);\r\n ball.setAttributeNS(null, 'cy', y + this.offsetY);\r\n ball.setAttributeNS(null, 'r', this.opts.bondLength / 4.5);\r\n ball.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n\r\n this.vertices.push(ball);\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone(),\r\n normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral(),\r\n start,\r\n end;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n } else {\r\n start = l;\r\n end = r;\r\n }\r\n\r\n let dir = Vector2.subtract(end, start).normalize(),\r\n length = line.getLength(),\r\n step = 1.25 / (length / (this.opts.bondThickness * 3.0)),\r\n changed = false;\r\n\r\n let gradient = this.createGradient(line);\r\n\r\n for (let t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length),\r\n startDash = Vector2.add(start, to),\r\n width = 1.5 * t,\r\n dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n startDash.subtract(dashOffset);\r\n let endDash = startDash.clone();\r\n endDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n\r\n this.drawLine(new Line(startDash, endDash), null, gradient);\r\n }\r\n }\r\n\r\n /**\r\n * Draws a debug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + this.offsetX);\r\n point.setAttributeNS(null, 'cy', y + this.offsetY);\r\n point.setAttributeNS(null, 'r', '2');\r\n point.setAttributeNS(null, 'fill', '#f00');\r\n this.vertices.push(point);\r\n this.drawDebugText(x, y, debugText);\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\r\n textElem.setAttributeNS(null, 'x', x + this.offsetX);\r\n textElem.setAttributeNS(null, 'y', y + this.offsetY);\r\n textElem.setAttributeNS(null, 'class', 'debug');\r\n textElem.setAttributeNS(null, 'fill', '#ff0000');\r\n textElem.setAttributeNS(null, 'style', `\r\n font: 5px Droid Sans, sans-serif;\r\n `);\r\n textElem.appendChild(document.createTextNode(text));\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * Draws a line.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} dashed defaults to false.\r\n * @param {String} gradient gradient url. Defaults to null.\r\n */\r\n drawLine(line, dashed = false, gradient = null) {\r\n let opts = this.opts,\r\n stylesArr = [\r\n ['stroke-linecap', 'round'],\r\n ['stroke-dasharray', dashed ? '5, 5' : 'none'],\r\n ],\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n let styles = stylesArr.map(sub => sub.join(':')).join(';'),\r\n lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line');\r\n\r\n lineElem.setAttributeNS(null, 'x1', fromX);\r\n lineElem.setAttributeNS(null, 'y1', fromY);\r\n lineElem.setAttributeNS(null, 'x2', toX);\r\n lineElem.setAttributeNS(null, 'y2', toY);\r\n lineElem.setAttributeNS(null, 'style', styles);\r\n this.paths.push(lineElem);\r\n\r\n if (gradient == null) {\r\n gradient = this.createGradient(line, fromX, fromY, toX, toY);\r\n }\r\n lineElem.setAttributeNS(null, 'stroke', `url('#${gradient}')`);\r\n }\r\n\r\n /**\r\n * Draw a point.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // first create a mask\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', x + offsetX);\r\n mask.setAttributeNS(null, 'cy', y + offsetY);\r\n mask.setAttributeNS(null, 'r', '1.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // now create the point\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + offsetX);\r\n point.setAttributeNS(null, 'cy', y + offsetY);\r\n point.setAttributeNS(null, 'r', '0.75');\r\n point.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n this.vertices.push(point);\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n pos = {\r\n x: x + offsetX,\r\n y: y + offsetY,\r\n },\r\n textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text'),\r\n writingMode = 'horizontal-tb',\r\n letterSpacing = 'normal',\r\n textOrientation = 'mixed',\r\n textDirection = 'direction: ltr;',\r\n xShift = -2,\r\n yShift = 2.5;\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', pos.x);\r\n mask.setAttributeNS(null, 'cy', pos.y);\r\n mask.setAttributeNS(null, 'r', '3.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // determine writing mode\r\n if (/up|down/.test(direction) && !isTerminal) {\r\n writingMode = 'vertical-rl';\r\n textOrientation = 'upright';\r\n letterSpacing = '-1px';\r\n }\r\n\r\n if (direction === 'down' && !isTerminal) {\r\n xShift = 0;\r\n yShift = -2;\r\n } else if (direction === 'up' && !isTerminal) {\r\n xShift = 0.5;\r\n } else if (direction === 'left') {\r\n xShift = 2;\r\n }\r\n\r\n if (direction === 'left' || (direction === 'up' && !isTerminal)) {\r\n textDirection = 'direction: rtl; unicode-bidi: bidi-override;'\r\n }\r\n\r\n // now the text element\r\n textElem.setAttributeNS(null, 'x', pos.x + xShift);\r\n textElem.setAttributeNS(null, 'y', pos.y + yShift);\r\n textElem.setAttributeNS(null, 'class', 'element');\r\n textElem.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n textElem.setAttributeNS(null, 'style', `\r\n text-anchor: start;\r\n writing-mode: ${writingMode};\r\n text-orientation: ${textOrientation};\r\n letter-spacing: ${letterSpacing};\r\n ${textDirection}\r\n `);\r\n\r\n let textNode = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n // special case for element names that are 2 letters\r\n if (elementName.length > 1) {\r\n let textAnchor = /up|down/.test(direction) ? 'middle' : 'start';\r\n\r\n textNode.setAttributeNS(null, 'style', `\r\n unicode-bidi: plaintext;\r\n writing-mode: lr-tb;\r\n letter-spacing: normal;\r\n text-anchor: ${textAnchor};\r\n `);\r\n }\r\n textNode.appendChild(document.createTextNode(elementName));\r\n textElem.appendChild(textNode);\r\n\r\n // Charge\r\n if (charge) {\r\n let chargeElem = this.createSubSuperScripts(getChargeText(charge), 'super');\r\n textNode.appendChild(chargeElem);\r\n }\r\n\r\n let isotopeText = '0';\r\n\r\n if (isotope > 0) {\r\n let isotopeElem = this.createSubSuperScripts(isotope.toString(), 'super');\r\n textNode.appendChild(isotopeElem);\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') &&\r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = {\r\n '0O': {\r\n element: 'O',\r\n count: 2,\r\n hydrogenCount: 0,\r\n previousElement: 'C',\r\n charge: ''\r\n }\r\n }\r\n charge = 0;\r\n }\r\n\r\n if (hydrogens > 0) {\r\n let hydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n hydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n hydrogenElem.appendChild(document.createTextNode('H'));\r\n textElem.appendChild(hydrogenElem);\r\n\r\n if (hydrogens > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogens, 'sub');\r\n hydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let element = attachedPseudoElement[key].element,\r\n elementCount = attachedPseudoElement[key].count,\r\n hydrogenCount = attachedPseudoElement[key].hydrogenCount,\r\n elementCharge = attachedPseudoElement[key].charge,\r\n pseudoElementElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoElementElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoElementElem.appendChild(document.createTextNode(element));\r\n pseudoElementElem.setAttributeNS(null, 'fill', this.themeManager.getColor(element));\r\n\r\n if (elementCharge !== 0) {\r\n let elementChargeElem = this.createSubSuperScripts(getChargeText(elementCharge), 'super');\r\n pseudoElementElem.appendChild(elementChargeElem);\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n let pseudoHydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoHydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoHydrogenElem.appendChild(document.createTextNode('H'));\r\n pseudoElementElem.appendChild(pseudoHydrogenElem);\r\n\r\n if (hydrogenCount > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogenCount, 'sub');\r\n pseudoHydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n if (elementCount > 1) {\r\n let elementCountElem = this.createSubSuperScripts(elementCount, 'sub');\r\n pseudoElementElem.appendChild(elementCountElem);\r\n }\r\n\r\n textElem.appendChild(pseudoElementElem);\r\n }\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * @param {Line} line the line object to create the wedge from\r\n */\r\n drawWedge(line) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l,\r\n end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness)),\r\n u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness)),\r\n v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness)),\r\n w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n let polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'),\r\n gradient = this.createGradient(line, l.x, l.y, r.x, r.y);\r\n polygon.setAttributeNS(null, 'points', `${t.x},${t.y} ${u.x},${u.y} ${v.x},${v.y} ${w.x},${w.y}`);\r\n polygon.setAttributeNS(null, 'fill', `url('#${gradient}')`);\r\n this.paths.push(polygon);\r\n }\r\n}\r\n\r\nmodule.exports = SvgWrapper;","class ThemeManager {\r\n constructor(colors, theme) {\r\n this.colors = colors;\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n if (key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.theme) {\r\n return this.theme[key];\r\n }\r\n }\r\n\r\n return this.theme['C'];\r\n }\r\n\r\n /**\r\n * Sets the theme to the specified string if it exists. If it does not, this\r\n * does nothing.\r\n *\r\n * @param {String} theme the name of the theme to switch to\r\n */\r\n setTheme(theme) {\r\n if (this.colors.hasOwnProperty(theme)) {\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n // TODO: this probably should notify those who are watching this theme\r\n // manager that the theme has changed so that colors can be changed\r\n // on the fly\r\n }\r\n}\r\n\r\nmodule.exports = ThemeManager;","/**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\nfunction getChargeText(charge) {\r\n console.log('in the utility version of getChargeText');\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n getChargeText,\r\n}","//@ts-check\r\n\r\n/** \r\n * A class representing a 2D vector.\r\n * \r\n * @property {Number} x The x component of the vector.\r\n * @property {Number} y The y component of the vector.\r\n */\r\nclass Vector2 {\r\n /**\r\n * The constructor of the class Vector2.\r\n *\r\n * @param {(Number|Vector2)} x The initial x coordinate value or, if the single argument, a Vector2 object.\r\n * @param {Number} y The initial y coordinate value.\r\n */\r\n constructor(x, y) {\r\n if (arguments.length == 0) {\r\n this.x = 0;\r\n this.y = 0;\r\n } else if (arguments.length == 1) {\r\n this.x = x.x;\r\n this.y = x.y;\r\n } else {\r\n this.x = x;\r\n this.y = y;\r\n }\r\n }\r\n\r\n /**\r\n * Clones this vector and returns the clone.\r\n *\r\n * @returns {Vector2} The clone of this vector.\r\n */\r\n clone() {\r\n return new Vector2(this.x, this.y);\r\n }\r\n\r\n /**\r\n * Returns a string representation of this vector.\r\n *\r\n * @returns {String} A string representation of this vector.\r\n */\r\n toString() {\r\n return '(' + this.x + ',' + this.y + ')';\r\n }\r\n\r\n /**\r\n * Add the x and y coordinate values of a vector to the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n add(vec) {\r\n this.x += vec.x;\r\n this.y += vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Subtract the x and y coordinate values of a vector from the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n subtract(vec) {\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Divide the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n divide(scalar) {\r\n this.x /= scalar;\r\n this.y /= scalar;\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Multiply the x and y coordinate values of this vector by the values of another vector.\r\n *\r\n * @param {Vector2} v A vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiply(v) {\r\n this.x *= v.x;\r\n this.y *= v.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Multiply the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiplyScalar(scalar) {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Inverts this vector. Same as multiply(-1.0).\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n invert() {\r\n this.x = -this.x;\r\n this.y = -this.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vector in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n angle() {\r\n return Math.atan2(this.y, this.x);\r\n }\r\n\r\n /**\r\n * Returns the euclidean distance between this vector and another vector.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Number} The euclidean distance between the two vectors.\r\n */\r\n distance(vec) {\r\n return Math.sqrt((vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y));\r\n }\r\n\r\n /**\r\n * Returns the squared euclidean distance between this vector and another vector. When only the relative distances of a set of vectors are needed, this is is less expensive than using distance(vec).\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} The squared euclidean distance of the two vectors.\r\n */\r\n distanceSq(vec) {\r\n return (vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to the coordinate system.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to the coordinate system.\r\n */\r\n clockwise(vec) {\r\n let a = this.y * vec.x;\r\n let b = this.x * vec.y;\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to an arbitrary third vector.\r\n *\r\n * @param {Vector2} center The central vector.\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to an arbitrary third vector.\r\n */\r\n relativeClockwise(center, vec) {\r\n let a = (this.y - center.y) * (vec.x - center.x);\r\n let b = (this.x - center.x) * (vec.y - center.y);\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Rotates this vector by a given number of radians around the origin of the coordinate system.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotate(angle) {\r\n let tmp = new Vector2(0, 0);\r\n let cosAngle = Math.cos(angle);\r\n let sinAngle = Math.sin(angle);\r\n\r\n tmp.x = this.x * cosAngle - this.y * sinAngle;\r\n tmp.y = this.x * sinAngle + this.y * cosAngle;\r\n \r\n this.x = tmp.x;\r\n this.y = tmp.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this vector around another vector.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @param {Vector2} vec The vector which is used as the rotational center.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateAround(angle, vec) {\r\n let s = Math.sin(angle);\r\n let c = Math.cos(angle);\r\n\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n let x = this.x * c - this.y * s;\r\n let y = this.x * s + this.y * c;\r\n\r\n this.x = x + vec.x;\r\n this.y = y + vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate a vector around a given center to the same angle as another vector (so that the two vectors and the center are in a line, with both vectors on one side of the center), keeps the distance from this vector to the center.\r\n *\r\n * @param {Vector2} vec The vector to rotate this vector to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} [offsetAngle=0.0] An additional amount of radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateTo(vec, center, offsetAngle = 0.0) {\r\n // Problem if this is first position\r\n this.x += 0.001;\r\n this.y -= 0.001;\r\n\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n\r\n this.rotateAround(angle + offsetAngle, center);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates the vector away from a specified vector around a center.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n */\r\n rotateAwayFrom(vec, center, angle) {\r\n this.rotateAround(angle, center);\r\n \r\n let distSqA = this.distanceSq(vec);\r\n \r\n this.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = this.distanceSq(vec);\r\n\r\n // If it was rotated towards the other vertex, rotate in other direction by same amount.\r\n if (distSqB < distSqA) {\r\n this.rotateAround(2.0 * angle, center);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector away from a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateAwayFromAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB < distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector towards a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated towards to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateTowardsAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB > distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the angles between this vector and another vector around a common center of rotation.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @param {Vector2} center The center of rotation.\r\n * @returns {Number} The angle between this vector and another vector around a center of rotation in radians.\r\n */\r\n getRotateToAngle(vec, center) {\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n \r\n return Number.isNaN(angle) ? 0.0 : angle;\r\n }\r\n\r\n /**\r\n * Checks whether a vector lies within a polygon spanned by a set of vectors.\r\n *\r\n * @param {Vector2[]} polygon An array of vectors spanning the polygon.\r\n * @returns {Boolean} A boolean indicating whether or not this vector is within a polygon.\r\n */\r\n isInPolygon(polygon) {\r\n let inside = false;\r\n\r\n // Its not always a given, that the polygon is convex (-> sugars)\r\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\r\n if (((polygon[i].y > this.y) != (polygon[j].y > this.y)) &&\r\n (this.x < (polygon[j].x - polygon[i].x) * (this.y - polygon[i].y) /\r\n (polygon[j].y - polygon[i].y) + polygon[i].x)) {\r\n inside = !inside;\r\n }\r\n }\r\n\r\n\r\n return inside;\r\n }\r\n\r\n /**\r\n * Returns the length of this vector.\r\n *\r\n * @returns {Number} The length of this vector.\r\n */\r\n length() {\r\n return Math.sqrt((this.x * this.x) + (this.y * this.y));\r\n }\r\n\r\n /**\r\n * Returns the square of the length of this vector.\r\n *\r\n * @returns {Number} The square of the length of this vector.\r\n */\r\n lengthSq() {\r\n return (this.x * this.x) + (this.y * this.y);\r\n }\r\n\r\n /**\r\n * Normalizes this vector.\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n normalize() {\r\n this.divide(this.length());\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns a normalized copy of this vector.\r\n *\r\n * @returns {Vector2} A normalized copy of this vector.\r\n */\r\n normalized() {\r\n return Vector2.divideScalar(this, this.length());\r\n }\r\n\r\n /**\r\n * Calculates which side of a line spanned by two vectors this vector is.\r\n *\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} A number indicating the side of this vector, given a line spanned by two other vectors.\r\n */\r\n whichSide(vecA, vecB) {\r\n return (this.x - vecA.x) * (vecB.y - vecA.y) - (this.y - vecA.y) * (vecB.x - vecA.x);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is on the same side of a line spanned by two vectors as another vector.\r\n *\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @param {Vector2} vecC A vector to check whether or not it is on the same side as this vector.\r\n * @returns {Boolean} Returns a boolean indicating whether or not this vector is on the same side as another vector.\r\n */\r\n sameSideAs(vecA, vecB, vecC) {\r\n let d = this.whichSide(vecA, vecB);\r\n let dRef = vecC.whichSide(vecA, vecB);\r\n\r\n return d < 0 && dRef < 0 || d == 0 && dRef == 0 || d > 0 && dRef > 0;\r\n }\r\n\r\n /**\r\n * Adds two vectors and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A summand.\r\n * @param {Vector2} vecB A summand.\r\n * @returns {Vector2} Returns the sum of two vectors.\r\n */\r\n static add(vecA, vecB) {\r\n return new Vector2(vecA.x + vecB.x, vecA.y + vecB.y);\r\n }\r\n\r\n /**\r\n * Subtracts one vector from another and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The minuend.\r\n * @param {Vector2} vecB The subtrahend.\r\n * @returns {Vector2} Returns the difference of two vectors.\r\n */\r\n static subtract(vecA, vecB) {\r\n return new Vector2(vecA.x - vecB.x, vecA.y - vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiply(vecA, vecB) {\r\n return new Vector2(vecA.x * vecB.x, vecA.y * vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vec A vector.\r\n * @param {Number} scalar A scalar.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiplyScalar(vec, scalar) {\r\n return new Vector2(vec.x, vec.y).multiplyScalar(scalar);\r\n }\r\n\r\n /**\r\n * Returns the midpoint of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2} The midpoint of the line spanned by two vectors.\r\n */\r\n static midpoint(vecA, vecB) {\r\n return new Vector2((vecA.x + vecB.x) / 2, (vecA.y + vecB.y) / 2);\r\n }\r\n\r\n /**\r\n * Returns the normals of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two normals, each represented by a vector.\r\n */\r\n static normals(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n new Vector2(-delta.y, delta.x),\r\n new Vector2(delta.y, -delta.x)\r\n ];\r\n }\r\n\r\n /**\r\n * Returns the unit (normalized normal) vectors of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two unit vectors.\r\n */\r\n static units(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n (new Vector2(-delta.y, delta.x)).normalize(),\r\n (new Vector2(delta.y, -delta.x)).normalize()\r\n ];\r\n }\r\n\r\n /**\r\n * Divides a vector by another vector and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Vector2} vecB The divisor.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divide(vecA, vecB) {\r\n return new Vector2(vecA.x / vecB.x, vecA.y / vecB.y);\r\n }\r\n\r\n /**\r\n * Divides a vector by a scalar and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Number} s The scalar.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divideScalar(vecA, s) {\r\n return new Vector2(vecA.x / s, vecA.y / s);\r\n }\r\n\r\n /**\r\n * Returns the dot product of two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The dot product of two vectors.\r\n */\r\n static dot(vecA, vecB) {\r\n return vecA.x * vecB.x + vecA.y * vecB.y;\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The angle between two vectors in radians.\r\n */\r\n static angle(vecA, vecB) {\r\n let dot = Vector2.dot(vecA, vecB);\r\n\r\n return Math.acos(dot / (vecA.length() * vecB.length()));\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors based on a third vector in between.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A (central) vector.\r\n * @param {Vector2} vecC A vector.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static threePointangle(vecA, vecB, vecC) {\r\n let ab = Vector2.subtract(vecB, vecA);\r\n let bc = Vector2.subtract(vecC, vecB);\r\n let abLength = vecA.distance(vecB);\r\n let bcLength = vecB.distance(vecC);\r\n\r\n return Math.acos(Vector2.dot(ab, bc) / (abLength * bcLength));\r\n }\r\n \r\n /**\r\n * Returns the scalar projection of a vector on another vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The vector to be projected.\r\n * @param {Vector2} vecB The vector to be projection upon.\r\n * @returns {Number} The scalar component.\r\n */\r\n static scalarProjection(vecA, vecB) {\r\n let unit = vecB.normalized();\r\n \r\n return Vector2.dot(vecA, unit);\r\n }\r\n\r\n /**\r\n * Returns the average vector (normalized) of the input vectors.\r\n *\r\n * @static\r\n * @param {Array} vecs An array containing vectors.\r\n * @returns {Vector2} The resulting vector (normalized).\r\n */\r\n static averageDirection(vecs) {\r\n let avg = new Vector2(0.0, 0.0);\r\n\r\n for (var i = 0; i < vecs.length; i++) {\r\n let vec = vecs[i];\r\n avg.add(vec);\r\n }\r\n\r\n return avg.normalize();\r\n }\r\n}\r\n\r\nmodule.exports = Vector2;","//@ts-check\r\nconst MathHelper = require('./MathHelper')\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Atom = require('./Atom')\r\nconst VertexState = require('./VertexState')\r\n\r\n/** \r\n * A class representing a vertex.\r\n * \r\n * @property {Number} id The id of this vertex.\r\n * @property {Atom} value The atom associated with this vertex.\r\n * @property {Vector2} position The position of this vertex.\r\n * @property {Vector2} previousPosition The position of the previous vertex.\r\n * @property {Number|null} parentVertexId The id of the previous vertex.\r\n * @property {Number[]} children The ids of the children of this vertex.\r\n * @property {Number[]} spanningTreeChildren The ids of the children of this vertex as defined in the spanning tree defined by the SMILES.\r\n * @property {Number[]} edges The ids of edges associated with this vertex.\r\n * @property {Boolean} positioned A boolean indicating whether or not this vertex has been positioned.\r\n * @property {Number} angle The angle of this vertex.\r\n * @property {Number} dir The direction of this vertex.\r\n * @property {Number} neighbourCount The number of neighbouring vertices.\r\n * @property {Number[]} neighbours The vertex ids of neighbouring vertices.\r\n * @property {String[]} neighbouringElements The element symbols associated with neighbouring vertices.\r\n * @property {Boolean} forcePositioned A boolean indicating whether or not this vertex was positioned using a force-based approach.\r\n * @property {Number} vertexState enum of VertexState for DFS.\r\n */\r\n\r\nclass Vertex {\r\n /**\r\n * The constructor for the class Vertex.\r\n *\r\n * @param {Atom} value The value associated with this vertex.\r\n * @param {Number} [x=0] The initial x coordinate of the positional vector of this vertex.\r\n * @param {Number} [y=0] The initial y coordinate of the positional vector of this vertex.\r\n */\r\n constructor(value, x = 0, y = 0) {\r\n this.id = null;\r\n this.value = value;\r\n this.position = new Vector2(x ? x : 0, y ? y : 0);\r\n this.previousPosition = new Vector2(0, 0);\r\n this.parentVertexId = null;\r\n this.children = Array();\r\n this.spanningTreeChildren = Array();\r\n this.edges = Array();\r\n this.positioned = false;\r\n this.angle = null;\r\n this.dir = 1.0;\r\n this.neighbourCount = 0;\r\n this.neighbours = Array();\r\n this.neighbouringElements = Array();\r\n this.forcePositioned = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n this.component = -1;\r\n this.digits = [];\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex.\r\n * \r\n * @param {Number} x The x component of the coordinates.\r\n * @param {Number} y The y component of the coordinates.\r\n * \r\n */\r\n setPosition(x, y) {\r\n this.position.x = x;\r\n this.position.y = y;\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex from a Vector2.\r\n * \r\n * @param {Vector2} v A 2D vector.\r\n * \r\n */\r\n setPositionFromVector(v) {\r\n this.position.x = v.x;\r\n this.position.y = v.y;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n */\r\n addChild(vertexId) {\r\n this.children.push(vertexId);\r\n this.neighbours.push(vertexId);\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex as the second child of the neighbours array,\r\n * except this vertex is the first vertex of the SMILE string, then it is added as the first.\r\n * This is used to get the correct ordering of neighbours for parity calculations.\r\n * If a hydrogen is implicitly attached to the chiral center, insert as the third child.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n * @param {Number} ringbondIndex The index of the ringbond.\r\n */\r\n addRingbondChild(vertexId, ringbondIndex) {\r\n this.children.push(vertexId);\r\n\r\n if (this.value.bracket) {\r\n let index = 1;\r\n\r\n if (this.id === 0 && this.value.bracket.hcount === 0) {\r\n index = 0;\r\n }\r\n \r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 0) {\r\n index = 2;\r\n }\r\n\r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 2;\r\n } else {\r\n index = 3;\r\n }\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 0) {\r\n index = 1;\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 1;\r\n } else {\r\n index = 2;\r\n }\r\n }\r\n \r\n this.neighbours.splice(index, 0, vertexId);\r\n } else {\r\n this.neighbours.push(vertexId);\r\n }\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Set the vertex id of the parent.\r\n * \r\n * @param {Number} parentVertexId The parents vertex id.\r\n */\r\n setParentVertexId(parentVertexId) {\r\n this.neighbourCount++;\r\n this.parentVertexId = parentVertexId;\r\n this.neighbours.push(parentVertexId);\r\n }\r\n\r\n /**\r\n * Returns true if this vertex is terminal (has no parent or child vertices), otherwise returns false. Always returns true if associated value has property hasAttachedPseudoElements set to true.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not this vertex is terminal.\r\n */\r\n isTerminal() {\r\n if (this.value.hasAttachedPseudoElements) {\r\n return true;\r\n }\r\n\r\n return (this.parentVertexId === null && this.children.length < 2) || this.children.length === 0;\r\n }\r\n\r\n /**\r\n * Clones this vertex and returns the clone.\r\n *\r\n * @returns {Vertex} A clone of this vertex.\r\n */\r\n clone() {\r\n let clone = new Vertex(this.value, this.position.x, this.position.y);\r\n clone.id = this.id;\r\n clone.previousPosition = new Vector2(this.previousPosition.x, this.previousPosition.y);\r\n clone.parentVertexId = this.parentVertexId;\r\n clone.children = ArrayHelper.clone(this.children);\r\n clone.spanningTreeChildren = ArrayHelper.clone(this.spanningTreeChildren);\r\n clone.edges = ArrayHelper.clone(this.edges);\r\n clone.positioned = this.positioned;\r\n clone.angle = this.angle;\r\n clone.forcePositioned = this.forcePositioned;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns true if this vertex and the supplied vertex both have the same id, else returns false.\r\n *\r\n * @param {Vertex} vertex The vertex to check.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices have the same id.\r\n */\r\n equals(vertex) {\r\n return this.id === vertex.id;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vertexes positional vector. If a reference vector is supplied in relations to this vector, else in relations to the coordinate system.\r\n *\r\n * @param {Vector2} [referenceVector=null] - The reference vector.\r\n * @param {Boolean} [returnAsDegrees=false] - If true, returns angle in degrees, else in radians.\r\n * @returns {Number} The angle of this vertex.\r\n */\r\n getAngle(referenceVector = null, returnAsDegrees = false) {\r\n let u = null;\r\n\r\n if (!referenceVector) {\r\n u = Vector2.subtract(this.position, this.previousPosition);\r\n } else {\r\n u = Vector2.subtract(this.position, referenceVector);\r\n }\r\n\r\n if (returnAsDegrees) {\r\n return MathHelper.toDeg(u.angle());\r\n }\r\n\r\n return u.angle();\r\n }\r\n\r\n /**\r\n * Returns the suggested text direction when text is added at the position of this vertex.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @returns {String} The suggested direction of the text.\r\n */\r\n getTextDirection(vertices) {\r\n let neighbours = this.getDrawnNeighbours(vertices);\r\n let angles = Array();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n angles.push(this.getAngle(vertices[neighbours[i]].position));\r\n }\r\n\r\n let textAngle = MathHelper.meanAngle(angles);\r\n\r\n // Round to 0, 90, 180 or 270 degree\r\n let halfPi = Math.PI / 2.0;\r\n textAngle = Math.round(Math.round(textAngle / halfPi) * halfPi);\r\n\r\n if (textAngle === 2) {\r\n return 'down';\r\n } else if (textAngle === -2) {\r\n return 'up';\r\n } else if (textAngle === 0 || textAngle === -0) {\r\n return 'right'; // is checking for -0 necessary?\r\n } else if (textAngle === 3 || textAngle === -3) {\r\n return 'left';\r\n } else {\r\n return 'down'; // default to down\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices.\r\n *\r\n * @param {Number} [vertexId=null] If a value is supplied, the vertex with this id is excluded from the returned indices.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices.\r\n */\r\n getNeighbours(vertexId = null) {\r\n if (vertexId === null) {\r\n return this.neighbours.slice();\r\n }\r\n\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (this.neighbours[i] !== vertexId) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices that will be drawn (vertex.value.isDrawn === true).\r\n * \r\n * @param {Vertex[]} vertices An array containing the vertices associated with the current molecule.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices that will be drawn.\r\n */\r\n getDrawnNeighbours(vertices) {\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (vertices[this.neighbours[i]].value.isDrawn) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns the number of neighbours of this vertex.\r\n *\r\n * @returns {Number} The number of neighbours.\r\n */\r\n getNeighbourCount() {\r\n return this.neighbourCount;\r\n }\r\n\r\n /**\r\n * Returns a list of ids of vertices neighbouring this one in the original spanning tree, excluding the ringbond connections.\r\n *\r\n * @param {Number} [vertexId=null] If supplied, the vertex with this id is excluded from the array returned.\r\n * @returns {Number[]} An array containing the ids of the neighbouring vertices.\r\n */\r\n getSpanningTreeNeighbours(vertexId = null) {\r\n let neighbours = Array();\r\n\r\n for (let i = 0; i < this.spanningTreeChildren.length; i++) {\r\n if (vertexId === undefined || vertexId != this.spanningTreeChildren[i]) {\r\n neighbours.push(this.spanningTreeChildren[i]);\r\n }\r\n }\r\n\r\n if (this.parentVertexId != null) {\r\n if (vertexId === undefined || vertexId != this.parentVertexId) {\r\n neighbours.push(this.parentVertexId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Gets the next vertex in the ring in opposide direction to the supplied vertex id.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @param {Number} ringId The id of the ring containing this vertex.\r\n * @param {Number} previousVertexId The id of the previous vertex. The next vertex will be opposite from the vertex with this id as seen from this vertex.\r\n * @returns {Number} The id of the next vertex in the ring.\r\n */\r\n getNextInRing(vertices, ringId, previousVertexId) {\r\n let neighbours = this.getNeighbours();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (ArrayHelper.contains(vertices[neighbours[i]].value.rings, {\r\n value: ringId\r\n }) &&\r\n neighbours[i] != previousVertexId) {\r\n return neighbours[i];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n\r\nmodule.exports = Vertex;","//@ts-check\r\n\r\nclass VertexState {\r\n\r\n /**\r\n * Enum values of Vertex State for DFS\r\n * @return {{NOT_FOUND: number, OPEN: number, CLOSED: number, FULLY_CLOSED: number}}\r\n */\r\n static get VALUES() {\r\n return { NOT_FOUND: 0, OPEN: 1, CLOSED: 2, FULLY_CLOSED: 3 };\r\n }\r\n}\r\n\r\nmodule.exports = VertexState;\r\n"]} \ No newline at end of file diff --git a/doc/ArrayHelper.html b/doc/ArrayHelper.html index c1dd67d1..efb937dd 100644 --- a/doc/ArrayHelper.html +++ b/doc/ArrayHelper.html @@ -3398,7 +3398,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/ArrayHelper.js.html b/doc/ArrayHelper.js.html index a4842723..71316b49 100644 --- a/doc/ArrayHelper.js.html +++ b/doc/ArrayHelper.js.html @@ -438,7 +438,7 @@

ArrayHelper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Atom.html b/doc/Atom.html index dc036b97..5556db12 100644 --- a/doc/Atom.html +++ b/doc/Atom.html @@ -2906,7 +2906,7 @@

restoreRi
- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Atom.js.html b/doc/Atom.js.html index 09c75409..703d86e0 100644 --- a/doc/Atom.js.html +++ b/doc/Atom.js.html @@ -594,7 +594,7 @@

Atom.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/CanvasWrapper.html b/doc/CanvasWrapper.html index deff0913..4f05fc9e 100644 --- a/doc/CanvasWrapper.html +++ b/doc/CanvasWrapper.html @@ -3783,7 +3783,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/CanvasWrapper.js.html b/doc/CanvasWrapper.js.html index a3b175a1..156d90fc 100644 --- a/doc/CanvasWrapper.js.html +++ b/doc/CanvasWrapper.js.html @@ -948,7 +948,7 @@

CanvasWrapper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/DecayPoint.js.html b/doc/DecayPoint.js.html index e6682524..464df510 100644 --- a/doc/DecayPoint.js.html +++ b/doc/DecayPoint.js.html @@ -73,7 +73,7 @@

DecayPoint.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Drawer.html b/doc/Drawer.html index 183c8e64..61ab8362 100644 --- a/doc/Drawer.html +++ b/doc/Drawer.html @@ -10857,7 +10857,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Drawer.js.html b/doc/Drawer.js.html index 4084e00e..de5c9462 100644 --- a/doc/Drawer.js.html +++ b/doc/Drawer.js.html @@ -3218,7 +3218,7 @@

Drawer.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Edge.html b/doc/Edge.html index 55622838..c9b360bb 100644 --- a/doc/Edge.html +++ b/doc/Edge.html @@ -1113,7 +1113,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Edge.js.html b/doc/Edge.js.html index d4e2b4cc..1c38aae4 100644 --- a/doc/Edge.js.html +++ b/doc/Edge.js.html @@ -134,7 +134,7 @@

Edge.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Graph.html b/doc/Graph.html index 8688ffef..7a181df0 100644 --- a/doc/Graph.html +++ b/doc/Graph.html @@ -635,7 +635,7 @@

(static)
Source:
@@ -795,7 +795,7 @@

(static) c
Source:
@@ -933,7 +933,7 @@

(static) fi
Source:
@@ -1100,7 +1100,7 @@

(static) f
Source:
@@ -1601,7 +1601,7 @@

(static) g
Source:
@@ -1750,7 +1750,7 @@

(static) Source:
@@ -1952,7 +1952,7 @@

Source:
@@ -2111,7 +2111,7 @@

Source:
@@ -2247,7 +2247,7 @@

(static) Source:
@@ -2470,7 +2470,7 @@

(static) <
Source:
@@ -2670,7 +2670,7 @@

(static) Source:
@@ -2873,7 +2873,7 @@

(st
Source:
@@ -3031,7 +3031,7 @@

Source:
@@ -3187,7 +3187,7 @@

(static) Source:
@@ -4427,7 +4427,7 @@

df
Source:
@@ -4564,7 +4564,7 @@

dfsSmilesSource:
@@ -4887,7 +4887,7 @@

Source:
@@ -8117,7 +8117,7 @@

startDfsSource:
@@ -8816,7 +8816,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Graph.js.html b/doc/Graph.js.html index e171ac3d..297e56e0 100644 --- a/doc/Graph.js.html +++ b/doc/Graph.js.html @@ -1235,9 +1235,7 @@

Graph.js

this.dfsSmallStart(); this._smallGraph.oneCyclic(); this._smallGraph.dfsSequenceStart(); - let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence); - return { blockSmiles: sequenceData.smiles, sequence: sequenceData.sequence, @@ -1892,7 +1890,7 @@

Graph.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Line.html b/doc/Line.html index 05333cd4..c983cb67 100644 --- a/doc/Line.html +++ b/doc/Line.html @@ -3056,7 +3056,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Line.js.html b/doc/Line.js.html index f77ae196..66fa79c3 100644 --- a/doc/Line.js.html +++ b/doc/Line.js.html @@ -358,7 +358,7 @@

Line.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MathHelper.html b/doc/MathHelper.html index 988590fc..e48b43aa 100644 --- a/doc/MathHelper.html +++ b/doc/MathHelper.html @@ -1869,7 +1869,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MathHelper.js.html b/doc/MathHelper.js.html index e42406de..2fc569ab 100644 --- a/doc/MathHelper.js.html +++ b/doc/MathHelper.js.html @@ -214,7 +214,7 @@

MathHelper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableBoolean.html b/doc/MutableBoolean.html index 3b0bf2e8..4a82b072 100644 --- a/doc/MutableBoolean.html +++ b/doc/MutableBoolean.html @@ -275,7 +275,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableBoolean.js.html b/doc/MutableBoolean.js.html index 49d6ca28..c15cb158 100644 --- a/doc/MutableBoolean.js.html +++ b/doc/MutableBoolean.js.html @@ -79,7 +79,7 @@

MutableBoolean.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableCounter.html b/doc/MutableCounter.html index 0d539ad8..66fbc6f5 100644 --- a/doc/MutableCounter.html +++ b/doc/MutableCounter.html @@ -223,7 +223,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableCounter.js.html b/doc/MutableCounter.js.html index 7c7dd0e9..e371ded1 100644 --- a/doc/MutableCounter.js.html +++ b/doc/MutableCounter.js.html @@ -80,7 +80,7 @@

MutableCounter.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Ring.html b/doc/Ring.html index 7c6948af..49361e42 100644 --- a/doc/Ring.html +++ b/doc/Ring.html @@ -1908,7 +1908,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Ring.js.html b/doc/Ring.js.html index f644525d..3fae9f31 100644 --- a/doc/Ring.js.html +++ b/doc/Ring.js.html @@ -267,7 +267,7 @@

Ring.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/RingConnection.html b/doc/RingConnection.html index 2986f307..2f723821 100644 --- a/doc/RingConnection.html +++ b/doc/RingConnection.html @@ -1602,7 +1602,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/RingConnection.js.html b/doc/RingConnection.js.html index 5f082165..49052597 100644 --- a/doc/RingConnection.js.html +++ b/doc/RingConnection.js.html @@ -216,7 +216,7 @@

RingConnection.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SSSR.html b/doc/SSSR.html index ec6ef75a..66f7a9ae 100644 --- a/doc/SSSR.html +++ b/doc/SSSR.html @@ -2524,7 +2524,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SSSR.js.html b/doc/SSSR.js.html index 29c93c63..9b3e0477 100644 --- a/doc/SSSR.js.html +++ b/doc/SSSR.js.html @@ -626,7 +626,7 @@

SSSR.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SvgDrawer.js.html b/doc/SvgDrawer.js.html index 1412ae78..aa0165d3 100644 --- a/doc/SvgDrawer.js.html +++ b/doc/SvgDrawer.js.html @@ -394,7 +394,7 @@

SvgDrawer.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SvgWrapper.js.html b/doc/SvgWrapper.js.html index 6890e62b..58306f86 100644 --- a/doc/SvgWrapper.js.html +++ b/doc/SvgWrapper.js.html @@ -659,7 +659,7 @@

SvgWrapper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/ThemeManager.js.html b/doc/ThemeManager.js.html index c324dde7..2b719bc9 100644 --- a/doc/ThemeManager.js.html +++ b/doc/ThemeManager.js.html @@ -97,7 +97,7 @@

ThemeManager.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/UtilityFunctions.js.html b/doc/UtilityFunctions.js.html index 46322931..2a07c87b 100644 --- a/doc/UtilityFunctions.js.html +++ b/doc/UtilityFunctions.js.html @@ -78,7 +78,7 @@

UtilityFunctions.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vector2.html b/doc/Vector2.html index ce705f26..630d55d7 100644 --- a/doc/Vector2.html +++ b/doc/Vector2.html @@ -7088,7 +7088,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vector2.js.html b/doc/Vector2.js.html index 7a6a5859..bc8e6d09 100644 --- a/doc/Vector2.js.html +++ b/doc/Vector2.js.html @@ -684,7 +684,7 @@

Vector2.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vertex.html b/doc/Vertex.html index e25ff58f..7ecd7c76 100644 --- a/doc/Vertex.html +++ b/doc/Vertex.html @@ -3036,7 +3036,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vertex.js.html b/doc/Vertex.js.html index e141dbf2..9478a075 100644 --- a/doc/Vertex.js.html +++ b/doc/Vertex.js.html @@ -403,7 +403,7 @@

Vertex.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/VertexState.js.html b/doc/VertexState.js.html index 69ff185a..69dec15e 100644 --- a/doc/VertexState.js.html +++ b/doc/VertexState.js.html @@ -70,7 +70,7 @@

VertexState.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/global.html b/doc/global.html index 5a0dd570..29fd9344 100644 --- a/doc/global.html +++ b/doc/global.html @@ -297,7 +297,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/index.html b/doc/index.html index ebc85c24..6390560b 100644 --- a/doc/index.html +++ b/doc/index.html @@ -381,7 +381,7 @@

Contributors


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 08:51:02 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/spec/blocksSpec.js b/spec/blocksSpec.js index c8651678..aa5c4881 100644 --- a/spec/blocksSpec.js +++ b/spec/blocksSpec.js @@ -15,6 +15,7 @@ const LINEARIZED_PSEUDACYCLIN_A = 'C(CCC(NC(=O)C(NC(=O)C)C(C)CC)C(=O)NC(CC1=CC=C const PYOVERDIN_PA_A = 'CC(C1C(=O)NC(C(=O)NCCCCC(C(=O)NC(C(=O)N1)CCCN(C=O)O)NC(=O)C(CCCN(C=O)O)NC(=O)C(CO)NC(=O)C(CCCN=C(N)N)NC(=O)C(CO)NC(=O)C2CCNC3=C(C=C4C=C(C(=O)C=C4N23)O)NC(=O)CCC(=O)O)C(C)O)O'; const MICAFUNGIN = 'CCCCCOC1=CC=C(C=C1)C2=CC(=NO2)C3=CC=C(C=C3)C(=O)NC4CC(C(NC(=O)C5C(C(CN5C(=O)C(NC(=O)C(NC(=O)C6CC(CN6C(=O)C(NC4=O)C(C)O)O)C(C(C7=CC(=C(C=C7)O)OS(=O)(=O)O)O)O)C(CC(=O)N)O)C)O)O)O'; const DESFERI_FERIOXAMINE_B = 'CC(=O)N(CCCCCNC(=O)CCC(=O)N(CCCCCNC(=O)CCC(=O)N(CCCCCN)O)O)O'; +const RHODOTULIC = 'CC(=O)N(CCCC1C(=O)NC(C(=O)N1)CCCN(C(=O)C)O)O'; describe("blocks", function () { let smilesDrawer = new SmilesDrawer.Drawer({drawDecayPoints: DecayState.VALUES.STANDARD}); @@ -326,4 +327,20 @@ describe("blocks", function () { expect(result).toEqual(expected); }); + it('rhodotulic', function () { + smilesDrawer.draw(SmilesDrawer.Parser.parse(RHODOTULIC), 'output-canvas', 'light', true); + let result = smilesDrawer.buildBlockSmiles(); + let expected = { + blockSmiles: [ + {smiles: 'OC(C(CCCN(C(C)=O)O)N)=O', isPolyketide: false}, + {smiles: 'NC(C(=O)O)CCCN(C(=O)C)O', isPolyketide: false}, + ], + sequence: '[0]-[1]', + sequenceType: 'cyclic', + decays: [9, 13], + isPolyketide: false // polyketide have to be true on both blocks, but not implemented yet + }; + expect(result).toEqual(expected); + }) + }); diff --git a/src/Graph.js b/src/Graph.js index 52963234..58807a6e 100644 --- a/src/Graph.js +++ b/src/Graph.js @@ -1191,9 +1191,7 @@ class Graph { this.dfsSmallStart(); this._smallGraph.oneCyclic(); this._smallGraph.dfsSequenceStart(); - let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence); - return { blockSmiles: sequenceData.smiles, sequence: sequenceData.sequence, diff --git a/src/SmallGraph.js b/src/SmallGraph.js index ffd2cd9f..09403685 100644 --- a/src/SmallGraph.js +++ b/src/SmallGraph.js @@ -54,7 +54,12 @@ class SmallGraph { } this.dfsInitialization(); this.isCyclic = false; - this.dfsCyclic(this._nodes[0], -1); + if (this._nodes.length === 2 && this._nodes[0].neighbours.length === 2 && this._nodes[1].neighbours.length === 2) { + this.isCyclic = true; + this._nodeOnRing = this._nodes[0]; + } else { + this.dfsCyclic(this._nodes[0], -1); + } } dfsCyclic(vertex, vertexFromId) { From 31ee66442ccedba83692db3b2823baa8910141cf Mon Sep 17 00:00:00 2001 From: privrja Date: Fri, 23 Apr 2021 10:39:55 +0200 Subject: [PATCH 4/6] Cyclic of 2 blocks --- app.js | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index fe598d2e..63dc3341 100644 --- a/app.js +++ b/app.js @@ -15,7 +15,7 @@ var canUseDOM = !!( * @typicalname SmilesDrawer */ var SmilesDrawer = { - Version: '2.1.5' + Version: '2.1.6' }; SmilesDrawer.Drawer = Drawer; diff --git a/package-lock.json b/package-lock.json index c99c203b..8d5c1b4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "smiles-drawer", - "version": "2.1.5", + "version": "2.1.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3c42a9d8..c5e04774 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "smiles-drawer", - "version": "2.1.5", + "version": "2.1.6", "description": "A SMILES drawer and parser. Generate molecular structure depictions in pure JavaScript. With new feature to compute building blocks from sequence.", "main": "./app.js", "repository": "https://github.com/privrja/smilesDrawer.git", From b2f08d9b335581d8e9114a4fb52ffaf38b38652f Mon Sep 17 00:00:00 2001 From: privrja Date: Fri, 23 Apr 2021 10:46:49 +0200 Subject: [PATCH 5/6] Cyclic of 2 blocks --- dist/smiles-drawer.js | 2 +- dist/smiles-drawer.min.js | 2 +- dist/smiles-drawer.min.js.map | 2 +- doc/ArrayHelper.html | 2 +- doc/ArrayHelper.js.html | 2 +- doc/Atom.html | 2 +- doc/Atom.js.html | 2 +- doc/CanvasWrapper.html | 2 +- doc/CanvasWrapper.js.html | 2 +- doc/DecayPoint.js.html | 2 +- doc/Drawer.html | 2 +- doc/Drawer.js.html | 2 +- doc/Edge.html | 2 +- doc/Edge.js.html | 2 +- doc/Graph.html | 2 +- doc/Graph.js.html | 2 +- doc/Line.html | 2 +- doc/Line.js.html | 2 +- doc/MathHelper.html | 2 +- doc/MathHelper.js.html | 2 +- doc/MutableBoolean.html | 2 +- doc/MutableBoolean.js.html | 2 +- doc/MutableCounter.html | 2 +- doc/MutableCounter.js.html | 2 +- doc/Ring.html | 2 +- doc/Ring.js.html | 2 +- doc/RingConnection.html | 2 +- doc/RingConnection.js.html | 2 +- doc/SSSR.html | 2 +- doc/SSSR.js.html | 2 +- doc/SvgDrawer.js.html | 2 +- doc/SvgWrapper.js.html | 2 +- doc/ThemeManager.js.html | 2 +- doc/UtilityFunctions.js.html | 2 +- doc/Vector2.html | 2 +- doc/Vector2.js.html | 2 +- doc/Vertex.html | 2 +- doc/Vertex.js.html | 2 +- doc/VertexState.js.html | 2 +- doc/global.html | 2 +- doc/index.html | 2 +- package-lock.json | 8406 --------------------------------- 42 files changed, 41 insertions(+), 8447 deletions(-) delete mode 100644 package-lock.json diff --git a/dist/smiles-drawer.js b/dist/smiles-drawer.js index 15a1f12e..f49b2815 100644 --- a/dist/smiles-drawer.js +++ b/dist/smiles-drawer.js @@ -16,7 +16,7 @@ var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.do */ var SmilesDrawer = { - Version: '2.1.5' + Version: '2.1.6' }; SmilesDrawer.Drawer = Drawer; SmilesDrawer.Parser = Parser; diff --git a/dist/smiles-drawer.min.js b/dist/smiles-drawer.min.js index 44d830fe..5e87c18a 100644 --- a/dist/smiles-drawer.min.js +++ b/dist/smiles-drawer.min.js @@ -1,4 +1,4 @@ -(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i{const context=canvas.getContext("2d");context.clearRect(0,0,canvas.width,canvas.height)})},SmilesDrawer.parse=function(smiles,successCallback,errorCallback){try{successCallback&&successCallback(Parser.parse(smiles))}catch(err){errorCallback&&errorCallback(err)}},canUseDOM&&(window.SmilesDrawer=SmilesDrawer),Array.prototype.fill||Object.defineProperty(Array.prototype,"fill",{value:function(value){if(null==this)throw new TypeError("this is null or not defined");for(var O=Object(this),len=O.length>>>0,start=arguments[1],relativeStart=start>>0,k=0>relativeStart?_Mathmax(len+relativeStart,0):_Mathmin(relativeStart,len),end=arguments[2],relativeEnd=void 0===end?len:end>>0,final=0>relativeEnd?_Mathmax(len+relativeEnd,0):_Mathmin(relativeEnd,len);kp.x&&(minX=p.x),minY>p.y&&(minY=p.y)}var padding=this.opts.padding;maxX+=padding,maxY+=padding,minX-=padding,minY-=padding,this.drawingWidth=maxX-minX,this.drawingHeight=maxY-minY;var scaleX=this.canvas.offsetWidth/this.drawingWidth,scaleY=this.canvas.offsetHeight/this.drawingHeight,scale=scaleXalpha&&(ctx.globalAlpha=alpha),ctx.strokeStyle=gradient,ctx.stroke(),ctx.restore()}drawWedge(line,width=1){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,shortLine=line.clone().shorten(5),l=shortLine.getLeftVector().clone(),r=shortLine.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone(),l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),start=l,end=r;isRightChiralCenter&&(start=r,end=l);let t=Vector2.add(start,Vector2.multiplyScalar(normals[0],this.halfBondThickness)),u=Vector2.add(end,Vector2.multiplyScalar(normals[0],1.5+this.halfBondThickness)),v=Vector2.add(end,Vector2.multiplyScalar(normals[1],1.5+this.halfBondThickness)),w=Vector2.add(start,Vector2.multiplyScalar(normals[1],this.halfBondThickness));ctx.beginPath(),ctx.moveTo(t.x,t.y),ctx.lineTo(u.x,u.y),ctx.lineTo(v.x,v.y),ctx.lineTo(w.x,w.y);let gradient=this.ctx.createRadialGradient(r.x,r.y,this.opts.bondLength,r.x,r.y,0);gradient.addColorStop(.4,this.themeManager.getColor(line.getLeftElement())||this.themeManager.getColor("C")),gradient.addColorStop(.6,this.themeManager.getColor(line.getRightElement())||this.themeManager.getColor("C")),ctx.fillStyle=gradient,ctx.fill(),ctx.restore()}drawDashedWedge(line){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),shortLine=line.clone(),start,end,sStart,sEnd;isRightChiralCenter?(start=r,end=l,shortLine.shortenRight(1),sStart=shortLine.getRightVector().clone(),sEnd=shortLine.getLeftVector().clone()):(start=l,end=r,shortLine.shortenLeft(1),sStart=shortLine.getLeftVector().clone(),sEnd=shortLine.getRightVector().clone()),sStart.x+=offsetX,sStart.y+=offsetY,sEnd.x+=offsetX,sEnd.y+=offsetY;let dir=Vector2.subtract(end,start).normalize();ctx.strokeStyle=this.themeManager.getColor("C"),ctx.lineCap="round",ctx.lineWidth=this.opts.bondThickness,ctx.beginPath();let length=line.getLength(),step=1.25/(length/(3*this.opts.bondThickness)),changed=!1;for(var t=0;1>t;t+=step){let to=Vector2.multiplyScalar(dir,t*length),startDash=Vector2.add(start,to),width=1.5*t,dashOffset=Vector2.multiplyScalar(normals[0],width);!changed&&.5this.opts.fontSizeLarge?dim.width:this.opts.fontSizeLarge;r/=1.5,ctx.globalCompositeOperation="destination-out",ctx.beginPath(),ctx.arc(x+offsetX,y+offsetY,r,0,MathHelper.twoPI,!0),ctx.closePath(),ctx.fill(),ctx.globalCompositeOperation="source-over";let cursorPos=-dim.width/2,cursorPosLeft=-dim.width/2;ctx.fillStyle=this.themeManager.getColor(elementName),ctx.fillText(elementName,x+offsetX+cursorPos,y+this.opts.halfFontSizeLarge+offsetY),cursorPos+=dim.width,charge&&(ctx.font=this.fontSmall,ctx.fillText(chargeText,x+offsetX+cursorPos,y-this.opts.fifthFontSizeSmall+offsetY),cursorPos+=chargeWidth),0maxDist&&(maxDist=dist,a=i,b=j)}let angle=-Vector2.subtract(this.graph.vertices[a].position,this.graph.vertices[b].position).angle();if(!isNaN(angle)){let remainder=angle%.523599;.2617995>remainder?angle-=remainder:angle+=.523599-remainder;for(let i=0;i{if(counts.has(e)){let count=counts.get(e);molecularFormula+=e+(1vertexA.value.getRingbondCount()||1>vertexB.value.getRingbondCount())return null;for(var i=0;isubTreeDepthB&&(a=edge.sourceId,b=edge.targetId);let subTreeOverlap=this.getSubtreeOverlapScore(b,a,overlapScore.vertexScores);if(subTreeOverlap.value>this.opts.overlapSensitivity){let vertexA=this.graph.vertices[a],vertexB=this.graph.vertices[b],neighboursB=vertexB.getNeighbours(a);if(1===neighboursB.length){let neighbour=this.graph.vertices[neighboursB[0]],angle=neighbour.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbour.id,vertexB.id,angle,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?this.rotateSubtree(neighbour.id,vertexB.id,-angle,vertexB.position):this.totalOverlapScore=newTotalOverlapScore}else if(2===neighboursB.length){if(0!==vertexB.value.rings.length&&0!==vertexA.value.rings.length)continue;let neighbourA=this.graph.vertices[neighboursB[0]],neighbourB=this.graph.vertices[neighboursB[1]];if(1===neighbourA.value.rings.length&&1===neighbourB.value.rings.length){if(neighbourA.value.rings[0]!==neighbourB.value.rings[0])continue;}else if(0!==neighbourA.value.rings.length||0!==neighbourB.value.rings.length)continue;else{let angleA=neighbourA.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120)),angleB=neighbourB.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbourA.id,vertexB.id,angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,angleB,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?(this.rotateSubtree(neighbourA.id,vertexB.id,-angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,-angleB,vertexB.position)):this.totalOverlapScore=newTotalOverlapScore}}overlapScore=this.getOverlapScore()}}}this.resolveSecondaryOverlaps(overlapScore.scores),this.opts.isomeric&&this.annotateStereochemistry(),this.opts.compactDrawing&&"default"===this.opts.atomVisualization&&this.initPseudoElements(),this.rotateDrawing()}initRings(){let openBonds=new Map;for(let i=this.graph.vertices.length-1,vertex;0<=i;i--)if(vertex=this.graph.vertices[i],0!==vertex.value.ringbonds.length)for(let j=0;jneighbour.value.rings.length&&!neighbour.value.bridgedRing||neighbour.value.bridgedRing&&2>neighbour.value.originalRings.length)&&(vertex.value.isDrawn=!1)}}getBridgedRingRings(ringId){let involvedRings=[],that=this,recurse=function(r){let ring=that.getRing(r);involvedRings.push(r);for(let i=0,n;imaxSize&&(maxSize=size,largestCommonRing=ring)}return largestCommonRing}getVerticesAt(position,radius,excludeVertexId){let locals=[];for(let i=0,vertex;ii;){let a=this.graph.vertices[i],b=this.graph.vertices[j];if(!a.value.isDrawn||!b.value.isDrawn)continue;let dist=Vector2.subtract(a.position,b.position).lengthSq();if(disttotalSideCount[1]?0:1,sideCount:sideCount,position:sideCount[0]>sideCount[1]?0:1,anCount:anCount,bnCount:bnCount}}setRingCenter(ring){let ringSize=ring.getSize(),total=new Vector2(0,0);for(let i=0;is.sideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.sideCount[0]s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.totalSideCount[0]<=s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}}else if("#"===edge.bondType){normals[0].multiplyScalar(that.opts.bondSpacing/1.5),normals[1].multiplyScalar(that.opts.bondSpacing/1.5);let lineA=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)),lineB=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));this.canvasWrapper.drawLine(lineA),this.canvasWrapper.drawLine(lineB),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if("."===edge.bondType);else{let isChiralCenterA=vertexA.value.isStereoCenter,isChiralCenterB=vertexB.value.isStereoCenter;"up"===edge.wedge?this.canvasWrapper.drawWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):"down"===edge.wedge?this.canvasWrapper.drawDashedWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay)))}if(debug){let midpoint=Vector2.midpoint(a,b);this.canvasWrapper.drawDebugText(midpoint.x,midpoint.y,"e: "+edgeId)}}drawVertices(debug){for(let i=0;i_Mathabs(_MathPI-angle)&&this.canvasWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);this.canvasWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else;}if(this.opts.debug)for(let i=0,center;iring.rings.length)&&(vertex.angle=a,vertex.positioned=!0)},startVertexId,previousVertex?previousVertex.id:null);ring.positioned=!0,ring.center=center;for(let i=0,neighbour;iVector2.subtract(center,normals[0]).lengthSq()&&(nextCenter=normals[1]);let posA=Vector2.subtract(vertexA.position,nextCenter),posB=Vector2.subtract(vertexB.position,nextCenter);-1===posA.clockwise(posB)?!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexA,vertexB):!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexB,vertexA)}else if(1===vertices.length){ring.isSpiro=!0,neighbour.isSpiro=!0;let vertexA=this.graph.vertices[vertices[0]],nextCenter=Vector2.subtract(center,vertexA.position);nextCenter.invert(),nextCenter.normalize();let r=MathHelper.polyCircumradius(this.opts.bondLength,neighbour.getSize());nextCenter.multiplyScalar(r),nextCenter.add(vertexA.position),neighbour.positioned||this.createRing(neighbour,nextCenter,vertexA)}}for(let i=0;ithat.opts.overlapSensitivity&&(score+=s,count++);let position=that.graph.vertices[vertex.id].position.clone();position.multiplyScalar(s),center.add(position)}}),center.divide(score),{value:score/count,center:center}}getCurrentCenterOfMass(){let total=new Vector2(0,0),count=0;for(let i=0,vertex;itotal&&(this.rotateSubtree(a.id,overlap.common.id,2*angle,overlap.common.position),this.rotateSubtree(b.id,overlap.common.id,-2*angle,overlap.common.position))}else 1!==overlap.vertices.length||2!==overlap.rings.length}resolveSecondaryOverlaps(scores){for(let i=0;ithis.opts.overlapSensitivity){let vertex=this.graph.vertices[scores[i].id];if(vertex.isTerminal()){let closest=this.getClosestVertex(vertex);if(closest){let closestPosition=null;closestPosition=closest.isTerminal()?0===closest.id?this.graph.vertices[1].position:closest.previousPosition:0===closest.id?this.graph.vertices[1].position:closest.position;let vertexPreviousPosition=0===vertex.id?this.graph.vertices[1].position:vertex.previousPosition;vertex.position.rotateAwayFrom(closestPosition,vertexPreviousPosition,MathHelper.toRad(20))}}}}getLastVertexWithAngle(vertexId){let angle=0,vertex=null;for(;!angle&&vertexId;)vertex=this.graph.vertices[vertexId],angle=vertex.angle,vertexId=vertex.parentVertexId;return vertex}createNextBond(vertex,previousVertex=null,angle=0,originShortest=!1,skipPositioning=!1){if(vertex.positioned&&!skipPositioning)return;let doubleBondConfigSet=!1;if(previousVertex){let edge=this.graph.getEdge(vertex.id,previousVertex.id);("/"===edge.bondType||"\\"===edge.bondType)&&1==++this.doubleBondConfigCount%2&&null===this.doubleBondConfig&&(this.doubleBondConfig=edge.bondType,doubleBondConfigSet=!0,null===previousVertex.parentVertexId&&vertex.value.branchBond&&("/"===this.doubleBondConfig?this.doubleBondConfig="\\":"\\"===this.doubleBondConfig&&(this.doubleBondConfig="/")))}if(!skipPositioning)if(!previousVertex){let dummy=new Vector2(this.opts.bondLength,0);dummy.rotate(MathHelper.toRad(-60)),vertex.previousPosition=dummy,vertex.setPosition(this.opts.bondLength,0),vertex.angle=MathHelper.toRad(-60),null===vertex.value.bridgedRing&&(vertex.positioned=!0)}else if(0a?_Mathmax2(-1.0472,a):1.0472;else if(!a){let v=this.getLastVertexWithAngle(vertex.id);a=v.angle,a||(a=1.0472)}if(previousVertex&&!doubleBondConfigSet){let bondType=this.graph.getEdge(vertex.id,nextVertex.id).bondType;"/"===bondType?("/"===this.doubleBondConfig||"\\"===this.doubleBondConfig&&(a=-a),this.doubleBondConfig=null):"\\"===bondType&&("/"===this.doubleBondConfig?a=-a:"\\"===this.doubleBondConfig,this.doubleBondConfig=null)}nextVertex.angle=originShortest?a:-a,this.createNextBond(nextVertex,vertex,previousAngle+nextVertex.angle)}}else if(2===neighbours.length){let a=vertex.angle;a||(a=1.0472);let subTreeDepthA=this.graph.getTreeDepth(neighbours[0],vertex.id),subTreeDepthB=this.graph.getTreeDepth(neighbours[1],vertex.id),l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]];l.value.subtreeDepth=subTreeDepthA,r.value.subtreeDepth=subTreeDepthB;let subTreeDepthC=this.graph.getTreeDepth(previousVertex?previousVertex.id:null,vertex.id);previousVertex&&(previousVertex.value.subtreeDepth=subTreeDepthC);let cis=0,trans=1;"C"===r.value.element&&"C"!==l.value.element&&1subTreeDepthA?(cis=1,trans=0):"C"!==r.value.element&&"C"===l.value.element&&1subTreeDepthB?(cis=0,trans=1):subTreeDepthB>subTreeDepthA&&(cis=1,trans=0);let cisVertex=this.graph.vertices[neighbours[cis]],transVertex=this.graph.vertices[neighbours[trans]],originShortest=!1;subTreeDepthCd1&&d2>d3?(s=this.graph.vertices[neighbours[1]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[2]]):d3>d1&&d3>d2&&(s=this.graph.vertices[neighbours[2]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]]),previousVertex&&1>previousVertex.value.rings.length&&1>s.value.rings.length&&1>l.value.rings.length&&1>r.value.rings.length&&1===this.graph.getTreeDepth(l.id,vertex.id)&&1===this.graph.getTreeDepth(r.id,vertex.id)&&1d1&&d2>d3&&d2>d4?(w=this.graph.vertices[neighbours[1]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[2]],z=this.graph.vertices[neighbours[3]]):d3>d1&&d3>d2&&d3>d4?(w=this.graph.vertices[neighbours[2]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[3]]):d4>d1&&d4>d2&&d4>d3&&(w=this.graph.vertices[neighbours[3]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[2]]),w.angle=-MathHelper.toRad(36),x.angle=MathHelper.toRad(36),y.angle=-MathHelper.toRad(108),z.angle=MathHelper.toRad(108),this.createNextBond(w,vertex,previousAngle+w.angle),this.createNextBond(x,vertex,previousAngle+x.angle),this.createNextBond(y,vertex,previousAngle+y.angle),this.createNextBond(z,vertex,previousAngle+z.angle)}}}getCommonRingbondNeighbour(vertex){let neighbours=vertex.neighbours;for(let i=0,neighbour;imaxLevels&&(maxLevels=priorities[j][1].length);for(let k=0;kmaxEntries&&(maxEntries=priorities[j][1][k].length)}for(let j=0,diff;jb[1][j][k])return-1;if(a[1][j][k]b[0]?-1:a[0]vertex.getNeighbourCount()||0heteroAtomCount)continue;let previous=null;for(let j=0,neighbour;jr.x+this.opts.mouseTolerance)&&(mouseY>l.y-this.opts.mouseTolerance&&mouseYr.y-this.opts.mouseTolerance&&mouseY{e.setDecay(!1)}),this.decays.forEach(e=>{this.edges[e].setDecay(!0)})}standardDecays(){for(let i=0;i{this.edges[e].setDecay(!0),this.edges[e].setDecayAll(!0),this.decays.push(e),this.decaysAll.push(e)})}isDecayPoint(sourceId,targetId,edgeBondId,decayTypes=DecayPoint.VALUES.ALL){switch(decayTypes){case DecayPoint.VALUES.ALL:let found=this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);return!1===found?this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId):found;case DecayPoint.VALUES.COO:return this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId);case DecayPoint.VALUES.CONH:return this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);}}getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"O",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"O",edgeBondId)}getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"N",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"N",edgeBondId)}getNeighbourEdgeDecayId(vertexId,element,edgeBondId){for(let i=0,edgeId;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getSubgraphDistanceMatrix(vertexIds){let length=vertexIds.length,adja=this.getSubgraphAdjacencyMatrix(vertexIds),dist=Array(length);for(var i=0;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getAdjacencyList(){let length=this.vertices.length,adjacencyList=Array(length);for(var i=0;imax&&(max=d)}return max+1}traverseTree(vertexId,parentVertexId,callback,maxDepth=999999,ignoreFirst=!1,depth=1,visited=null){if(null===visited&&(visited=new Uint8Array(this.vertices.length)),depth>maxDepth+1||1===visited[vertexId])return;visited[vertexId]=1;let vertex=this.vertices[vertexId],neighbours=vertex.getNeighbours(parentVertexId);(!ignoreFirst||1maxEnergy&&!1===arrPositioned[i]&&(maxEnergy=delta,maxEnergyId=i,maxDEX=dEX,maxDEY=dEY)}return[maxEnergyId,maxEnergy,maxDEX,maxDEY]},update=function(index,dEX,dEY){let dxx=0,dyy=0,dxy=0,ux=arrPositionX[index],uy=arrPositionY[index],arrL=matLength[index],arrK=matStrength[index];for(i=length;i--;){if(i===index)continue;let vx=arrPositionX[i],vy=arrPositionY[i],l=arrL[i],k=arrK[i],m=(ux-vx)*(ux-vx),denom=1/_Mathpow(m+(uy-vy)*(uy-vy),1.5);dxx+=k*(1-l*(uy-vy)*(uy-vy)*denom),dyy+=k*(1-l*m*denom),dxy+=k*(l*(ux-vx)*(uy-vy)*denom)}0==dxx&&(dxx=.1),0===dyy&&(dyy=.1),0===dxy&&(dxy=.1);let dy=dEX/dxx+dEY/dxy;dy/=dxy/dxx-dyy/dxy;let dx=-(dxy*dy+dEX)/dxx;arrPositionX[index]+=dx,arrPositionY[index]+=dy;let arrE=matEnergy[index];dEX=0,dEY=0,ux=arrPositionX[index],uy=arrPositionY[index];let vx,vy,prevEx,prevEy,denom;for(i=length;i--;)index!==i&&(vx=arrPositionX[i],vy=arrPositionY[i],prevEx=arrE[i][0],prevEy=arrE[i][1],denom=1/_Mathsqrt2((ux-vx)*(ux-vx)+(uy-vy)*(uy-vy)),dx=arrK[i]*(ux-vx-arrL[i]*(ux-vx)*denom),dy=arrK[i]*(uy-vy-arrL[i]*(uy-vy)*denom),arrE[i]=[dx,dy],dEX+=dx,dEY+=dy,arrEnergySumX[i]+=dx-prevEx,arrEnergySumY[i]+=dy-prevEy);arrEnergySumX[index]=dEX,arrEnergySumY[index]=dEY},maxEnergyId=0,dEX=0,dEY=0,delta=0,iteration=0,innerIteration=0;for(;maxEnergy>threshold&&maxIteration>iteration;)for(iteration++,[maxEnergyId,maxEnergy,dEX,dEY]=highestEnergy(),delta=maxEnergy,innerIteration=0;delta>innerThreshold&&maxInnerIteration>innerIteration;)innerIteration++,update(maxEnergyId,dEX,dEY),[delta,dEX,dEY]=energy(maxEnergyId);for(i=length;i--;){let index=vertexIds[i],vertex=this.vertices[index];vertex.position.x=arrPositionX[i],vertex.position.y=arrPositionY[i],vertex.positioned=!0,vertex.forcePositioned=!0}}_bridgeDfs(u,visited,disc,low,parent,adj,outBridges){visited[u]=!0,disc[u]=low[u]=++this._time;for(var i=0;idisc[u]&&outBridges.push([u,v]))}}static getConnectedComponents(adjacencyMatrix){let length=adjacencyMatrix.length,visited=Array(length),components=[],count=0;visited.fill(!1);for(var u=0;u=sequence.length)return{sequence:sequence,smiles:smiles};for(char=sequence.charAt(position);!isNaN(char);){if(number+=char,++position,position>=sequence.length)return{sequence:sequence,smiles:smiles};char=sequence.charAt(position)}let j;for(j=0;j=sequence.length)break;char=sequence.charAt(position)}return{sequence:newSequence,smiles:newSmiles}}getSequencePermutation(sequence){let match=null,permutation=[];for(;null!=(match=/\d+/g.exec(sequence));)permutation.push(match);return permutation}dfsSmallStart(){this._smallGraph=new SmallGraph;for(let index=0;indexdecaysCounter.getValue()&&!0===isPolyketide.getValue()&&isPolyketide.setValue(through.every(vertex=>"O"===vertex||"N"===vertex)&&4this.vertices[lastVertexId].digits.includes(e))&&(vertex.digits.push(this._digitCounter),this.vertices[lastVertexId].digits.push(this._digitCounter),this._digitCounter++)),vertex.vertexState===VertexState.VALUES.NOT_FOUND)&&"H"!==vertex.value.element){this.first===vertex.id&&"C"===vertex.value.element&&isPolyketide.getValue()&&(stackSmiles.push("O"),isPolyketide.setValue(!1)),vertex.value.bracket?(stackSmiles.push("["),Graph.printVertexValue(stackSmiles,vertex),0vertex.value.bracket.charge&&stackSmiles.push(vertex.value.bracket.charge),stackSmiles.push("]")):Graph.printVertexValue(stackSmiles,vertex),vertexCounter.increment(),isSecondPass&&stackSmiles.push(this.smilesNumbersAdd(vertex)),this._markComponent||this._startingVertexes.push(vertex),vertex.component=this._cnt,this._markComponent=!0,vertex.vertexState=VertexState.VALUES.OPEN;for(let i=0;i=smiles.length)););index--,numbers.add(num)}return numbers}static findFirst(smiles,number){return smiles.indexOf(number)}static findSecond(smiles,from,number){let result=smiles.indexOf(number,from);if(-1===result)throw"Not Found";return result}smilesNumbersAdd(vertex){let numbers="";for(let i=0,num;ie===num)){let nextVertex=this.vertices.find(e=>e.digits.includes(num)&&e.id!==vertex.id),intersection=vertex.edges.filter(element=>nextVertex.edges.includes(element));if(0peg$maxFailPos&&(peg$maxFailPos=peg$currPos,peg$maxFailExpected=[]),peg$maxFailExpected.push(expected))}function peg$buildSimpleError(message,location){return new peg$SyntaxError(message,null,null,location)}function peg$parsechain(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;if(s0=peg$currPos,s1=peg$currPos,s2=peg$parseatom(),s2!==peg$FAILED){for(s3=[],s4=peg$parsebranch();s4!==peg$FAILED;)s3.push(s4),s4=peg$parsebranch();if(s3!==peg$FAILED){for(s4=[],s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));s5!==peg$FAILED;)s4.push(s5),s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));if(s4!==peg$FAILED){for(s5=[],s6=peg$parsebranch();s6!==peg$FAILED;)s5.push(s6),s6=peg$parsebranch();if(s5===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s7=peg$parsechain(),s7===peg$FAILED&&(s7=null),s7!==peg$FAILED){for(s8=[],s9=peg$parsebranch();s9!==peg$FAILED;)s8.push(s9),s9=peg$parsebranch();s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8],s1=s2)}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c0(s1)),s0=s1,s0}function peg$parsebranch(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,40===input.charCodeAt(peg$currPos)?(s2="(",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c2)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parsebond(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s4=peg$parsechain(),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(41===input.charCodeAt(peg$currPos)?(s5=")",peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c4)),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5],s1=s2)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c5(s1)),s0=s1,s0}function peg$parseatom(){var s0,s1;return s0=peg$currPos,s1=peg$parseorganicsymbol(),s1===peg$FAILED&&(s1=peg$parsearomaticsymbol(),s1===peg$FAILED&&(s1=peg$parsebracketatom(),s1===peg$FAILED&&(s1=peg$parsewildcard()))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsebond(){var s0,s1;if(s0=peg$currPos,peg$c7.test(input.charAt(peg$currPos))){if(s1=input.charAt(peg$currPos),s1===input.charAt(peg$currPos+1))throw s1=peg$FAILED,peg$buildSimpleError("The parser encountered a bond repetition.",peg$currPos+1);peg$currPos++}else s1=peg$FAILED,peg$fail(peg$c8);return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c9(s1)),s0=s1,s0}function peg$parsebracketatom(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;return s0=peg$currPos,s1=peg$currPos,91===input.charCodeAt(peg$currPos)?(s2="[",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c11)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parseisotope(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):("se"===input.substr(peg$currPos,2)?(s4="se",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c13)),s4===peg$FAILED&&("as"===input.substr(peg$currPos,2)?(s4="as",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c15)),s4===peg$FAILED&&(s4=peg$parsearomaticsymbol(),s4===peg$FAILED&&(s4=peg$parseelementsymbol(),s4===peg$FAILED&&(s4=peg$parsewildcard())))),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s5=peg$parsechiral(),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s6=peg$parsehcount(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s7=peg$parsecharge(),s7===peg$FAILED&&(s7=null),s7===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s8=peg$parseclass(),s8===peg$FAILED&&(s8=null),s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(93===input.charCodeAt(peg$currPos)?(s9="]",peg$currPos++):(s9=peg$FAILED,peg$fail(peg$c17)),s9===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8,s9],s1=s2)))))))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c18(s1)),s0=s1,s0}function peg$parseorganicsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,66===input.charCodeAt(peg$currPos)?(s2="B",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c20)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(114===input.charCodeAt(peg$currPos)?(s3="r",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c22)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(s1=peg$currPos,67===input.charCodeAt(peg$currPos)?(s2="C",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c24)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(108===input.charCodeAt(peg$currPos)?(s3="l",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c26)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(peg$c27.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c28)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c29(s1)),s0=s1,s0}function peg$parsearomaticsymbol(){var s0,s1;return s0=peg$currPos,peg$c30.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c31)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsewildcard(){var s0,s1;return s0=peg$currPos,42===input.charCodeAt(peg$currPos)?(s1="*",peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c33)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c34(s1)),s0=s1,s0}function peg$parseelementsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,peg$c35.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c36)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c37.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c38)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c39(s1)),s0=s1,s0}function peg$parsering(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,37===input.charCodeAt(peg$currPos)?(s2="%",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c41)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c43)),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1===peg$FAILED&&(peg$c44.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c45))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c46(s1)),s0=s1,s0}function peg$parsechiral(){var s0,s1,s2,s3,s4,s5,s6;return s0=peg$currPos,s1=peg$currPos,64===input.charCodeAt(peg$currPos)?(s2="@",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c48)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(64===input.charCodeAt(peg$currPos)?(s3="@",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c48)),s3===peg$FAILED&&(s3=peg$currPos,"TH"===input.substr(peg$currPos,2)?(s4="TH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c50)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"AL"===input.substr(peg$currPos,2)?(s4="AL",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c54)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"SP"===input.substr(peg$currPos,2)?(s4="SP",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c56)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c57.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c58)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"TB"===input.substr(peg$currPos,2)?(s4="TB",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c60)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4))),s3===peg$FAILED&&(s3=peg$currPos,"OH"===input.substr(peg$currPos,2)?(s4="OH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c62)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4)))))))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c63(s1)),s0=s1,s0}function peg$parsecharge(){var s0,s1;return s0=peg$currPos,s1=peg$parseposcharge(),s1===peg$FAILED&&(s1=peg$parsenegcharge()),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c64(s1)),s0=s1,s0}function peg$parseposcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,43===input.charCodeAt(peg$currPos)?(s2="+",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c66)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(43===input.charCodeAt(peg$currPos)?(s3="+",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c66)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c67(s1)),s0=s1,s0}function peg$parsenegcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,45===input.charCodeAt(peg$currPos)?(s2="-",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c69)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(45===input.charCodeAt(peg$currPos)?(s3="-",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c69)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c70(s1)),s0=s1,s0}function peg$parsehcount(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,72===input.charCodeAt(peg$currPos)?(s2="H",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c72)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c73(s1)),s0=s1,s0}function peg$parseclass(){var s0,s1,s2,s3,s4,s5,s6;if(s0=peg$currPos,s1=peg$currPos,58===input.charCodeAt(peg$currPos)?(s2=":",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c75)),s2!==peg$FAILED){if(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4!==peg$FAILED){for(s5=[],peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s6!==peg$FAILED;)s5.push(s6),peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)}else peg$currPos=s3,s3=peg$FAILED;s3===peg$FAILED&&(peg$c76.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c77))),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c78(s1)),s0=s1,s0}function peg$parseisotope(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c43)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED&&(s4=null),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c79(s1)),s0=s1,s0}options=void 0===options?{}:options;var nOpenParentheses=input.split("(").length-1,nCloseParentheses=input.split(")").length-1;if(nOpenParentheses!==nCloseParentheses)throw peg$buildSimpleError("The number of opening parentheses does not match the number of closing parentheses.",0);var peg$FAILED={},peg$startRuleFunctions={chain:peg$parsechain},peg$startRuleFunction=peg$parsechain,peg$c0=function(s){for(var branches=[],rings=[],i=0;imax;){let prev=current;callback(prev),current=vertices[current].getNextInRing(vertices,this.id,previousVertexId),previousVertexId=prev,current==startVertexId&&(current=null),max++}}getOrderedNeighbours(ringConnections){let orderedNeighbours=Array(this.neighbours.length);for(let i=0,vertices;inewPathLength){var l,m,n;if(previousPathLength===newPathLength+1)for(pe_prime[i][j]=[pe[i][j].length],l=pe[i][j].length;l--;)for(pe_prime[i][j][l]=[pe[i][j][l].length],m=pe[i][j][l].length;m--;)for(pe_prime[i][j][l][m]=[pe[i][j][l][m].length],n=pe[i][j][l][m].length;n--;)pe_prime[i][j][l][m][n]=[pe[i][j][l][m][0],pe[i][j][l][m][1]];else pe_prime[i][j]=[];for(d[i][j]=newPathLength,pe[i][j]=[[]],l=pe[i][k][0].length;l--;)pe[i][j][0].push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)pe[i][j][0].push(pe[k][j][0][l])}else if(previousPathLength===newPathLength){if(pe[i][k].length&&pe[k][j].length){var l;if(pe[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j][0]=tmp}}}else if(previousPathLength===newPathLength-1){var l;if(pe_prime[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j][0]=tmp}}}return{d:d,pe:pe,pe_prime:pe_prime}}static getRingCandidates(d,pe,pe_prime){let length=d.length,candidates=[],c=0;for(let i=0;insssr)return cSssr}else for(let j=0,bonds;jnsssr)return cSssr}return cSssr}static getEdgeCount(adjacencyMatrix){let edgeCount=0,length=adjacencyMatrix.length;for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeCount++;return edgeCount}static getEdgeList(adjacencyMatrix){let length=adjacencyMatrix.length,edgeList=[];for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeList.push([i,j]);return edgeList}static bondsToAtoms(bonds){let atoms=new Set;for(var i=bonds.length;i--;)atoms.add(bonds[i][0]),atoms.add(bonds[i][1]);return atoms}static getBondCount(atoms,adjacencyMatrix){let count=0;for(let u of atoms)for(let v of atoms)u!==v&&(count+=adjacencyMatrix[u][v]);return count/2}static pathSetsContain(pathSets,pathSet,bonds,allBonds,arrBondCount,arrRingCount){for(var i=pathSets.length;i--;){if(SSSR.isSupersetOf(pathSet,pathSets[i]))return!0;if(pathSets[i].size===pathSet.size&&SSSR.areSetsEqual(pathSets[i],pathSet))return!0}let count=0,allContained=!1;for(i=bonds.length;i--;)for(var j=allBonds.length;j--;)(bonds[i][0]===allBonds[j][0]&&bonds[i][1]===allBonds[j][1]||bonds[i][1]===allBonds[j][0]&&bonds[i][0]===allBonds[j][1])&&count++,count===bonds.length&&(allContained=!0);let specialCase=!1;if(allContained)for(let element of pathSet)if(arrRingCount[element]e.vertexState=VertexState.VALUES.NOT_FOUND)}getSourceNode(){let ends=[];for(let index=0;indexthis._nodes[v].onRing=!0);continue}node.neighbours.forEach(neighbour=>{if(!path.some(e=>e===neighbour.neighbour)||neighbour.neighbour===start.id){let newPath=[...path];newPath.push(neighbour.neighbour),queue.push(newPath)}}),firstPass=!1}}sortByRingPreference(array){let sortedArray=[...array];return sortedArray.sort((a,b)=>this._nodes[a.neighbour].onRing===this._nodes[b.neighbour].onRing?a.direction>b.direction?-1:a.direction{let edges=graph.getEdges(vertex.id);for(var i=0;is.sideCount[1]||s.totalSideCount[0]>s.totalSideCount[1]){this.multiplyNormals(normals,opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB);line.shorten(opts.bondLength-opts.shortBondLength*opts.bondLength),svgWrapper.drawLine(line),svgWrapper.drawLine(new Line(a,b,elementA,elementB))}else if(s.sideCount[0]_Mathabs2(_MathPI3-angle)&&svgWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,vertex.value.chirality)}if(opts.debug)for(var i=0;i{const context=canvas.getContext("2d");context.clearRect(0,0,canvas.width,canvas.height)})},SmilesDrawer.parse=function(smiles,successCallback,errorCallback){try{successCallback&&successCallback(Parser.parse(smiles))}catch(err){errorCallback&&errorCallback(err)}},canUseDOM&&(window.SmilesDrawer=SmilesDrawer),Array.prototype.fill||Object.defineProperty(Array.prototype,"fill",{value:function(value){if(null==this)throw new TypeError("this is null or not defined");for(var O=Object(this),len=O.length>>>0,start=arguments[1],relativeStart=start>>0,k=0>relativeStart?_Mathmax(len+relativeStart,0):_Mathmin(relativeStart,len),end=arguments[2],relativeEnd=void 0===end?len:end>>0,final=0>relativeEnd?_Mathmax(len+relativeEnd,0):_Mathmin(relativeEnd,len);kp.x&&(minX=p.x),minY>p.y&&(minY=p.y)}var padding=this.opts.padding;maxX+=padding,maxY+=padding,minX-=padding,minY-=padding,this.drawingWidth=maxX-minX,this.drawingHeight=maxY-minY;var scaleX=this.canvas.offsetWidth/this.drawingWidth,scaleY=this.canvas.offsetHeight/this.drawingHeight,scale=scaleXalpha&&(ctx.globalAlpha=alpha),ctx.strokeStyle=gradient,ctx.stroke(),ctx.restore()}drawWedge(line,width=1){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,shortLine=line.clone().shorten(5),l=shortLine.getLeftVector().clone(),r=shortLine.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone(),l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),start=l,end=r;isRightChiralCenter&&(start=r,end=l);let t=Vector2.add(start,Vector2.multiplyScalar(normals[0],this.halfBondThickness)),u=Vector2.add(end,Vector2.multiplyScalar(normals[0],1.5+this.halfBondThickness)),v=Vector2.add(end,Vector2.multiplyScalar(normals[1],1.5+this.halfBondThickness)),w=Vector2.add(start,Vector2.multiplyScalar(normals[1],this.halfBondThickness));ctx.beginPath(),ctx.moveTo(t.x,t.y),ctx.lineTo(u.x,u.y),ctx.lineTo(v.x,v.y),ctx.lineTo(w.x,w.y);let gradient=this.ctx.createRadialGradient(r.x,r.y,this.opts.bondLength,r.x,r.y,0);gradient.addColorStop(.4,this.themeManager.getColor(line.getLeftElement())||this.themeManager.getColor("C")),gradient.addColorStop(.6,this.themeManager.getColor(line.getRightElement())||this.themeManager.getColor("C")),ctx.fillStyle=gradient,ctx.fill(),ctx.restore()}drawDashedWedge(line){if(isNaN(line.from.x)||isNaN(line.from.y)||isNaN(line.to.x)||isNaN(line.to.y))return;let ctx=this.ctx,offsetX=this.offsetX,offsetY=this.offsetY,l=line.getLeftVector().clone(),r=line.getRightVector().clone();l.x+=offsetX,l.y+=offsetY,r.x+=offsetX,r.y+=offsetY,ctx.save();let normals=Vector2.normals(l,r);normals[0].normalize(),normals[1].normalize();let isRightChiralCenter=line.getRightChiral(),shortLine=line.clone(),start,end,sStart,sEnd;isRightChiralCenter?(start=r,end=l,shortLine.shortenRight(1),sStart=shortLine.getRightVector().clone(),sEnd=shortLine.getLeftVector().clone()):(start=l,end=r,shortLine.shortenLeft(1),sStart=shortLine.getLeftVector().clone(),sEnd=shortLine.getRightVector().clone()),sStart.x+=offsetX,sStart.y+=offsetY,sEnd.x+=offsetX,sEnd.y+=offsetY;let dir=Vector2.subtract(end,start).normalize();ctx.strokeStyle=this.themeManager.getColor("C"),ctx.lineCap="round",ctx.lineWidth=this.opts.bondThickness,ctx.beginPath();let length=line.getLength(),step=1.25/(length/(3*this.opts.bondThickness)),changed=!1;for(var t=0;1>t;t+=step){let to=Vector2.multiplyScalar(dir,t*length),startDash=Vector2.add(start,to),width=1.5*t,dashOffset=Vector2.multiplyScalar(normals[0],width);!changed&&.5this.opts.fontSizeLarge?dim.width:this.opts.fontSizeLarge;r/=1.5,ctx.globalCompositeOperation="destination-out",ctx.beginPath(),ctx.arc(x+offsetX,y+offsetY,r,0,MathHelper.twoPI,!0),ctx.closePath(),ctx.fill(),ctx.globalCompositeOperation="source-over";let cursorPos=-dim.width/2,cursorPosLeft=-dim.width/2;ctx.fillStyle=this.themeManager.getColor(elementName),ctx.fillText(elementName,x+offsetX+cursorPos,y+this.opts.halfFontSizeLarge+offsetY),cursorPos+=dim.width,charge&&(ctx.font=this.fontSmall,ctx.fillText(chargeText,x+offsetX+cursorPos,y-this.opts.fifthFontSizeSmall+offsetY),cursorPos+=chargeWidth),0maxDist&&(maxDist=dist,a=i,b=j)}let angle=-Vector2.subtract(this.graph.vertices[a].position,this.graph.vertices[b].position).angle();if(!isNaN(angle)){let remainder=angle%.523599;.2617995>remainder?angle-=remainder:angle+=.523599-remainder;for(let i=0;i{if(counts.has(e)){let count=counts.get(e);molecularFormula+=e+(1vertexA.value.getRingbondCount()||1>vertexB.value.getRingbondCount())return null;for(var i=0;isubTreeDepthB&&(a=edge.sourceId,b=edge.targetId);let subTreeOverlap=this.getSubtreeOverlapScore(b,a,overlapScore.vertexScores);if(subTreeOverlap.value>this.opts.overlapSensitivity){let vertexA=this.graph.vertices[a],vertexB=this.graph.vertices[b],neighboursB=vertexB.getNeighbours(a);if(1===neighboursB.length){let neighbour=this.graph.vertices[neighboursB[0]],angle=neighbour.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbour.id,vertexB.id,angle,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?this.rotateSubtree(neighbour.id,vertexB.id,-angle,vertexB.position):this.totalOverlapScore=newTotalOverlapScore}else if(2===neighboursB.length){if(0!==vertexB.value.rings.length&&0!==vertexA.value.rings.length)continue;let neighbourA=this.graph.vertices[neighboursB[0]],neighbourB=this.graph.vertices[neighboursB[1]];if(1===neighbourA.value.rings.length&&1===neighbourB.value.rings.length){if(neighbourA.value.rings[0]!==neighbourB.value.rings[0])continue;}else if(0!==neighbourA.value.rings.length||0!==neighbourB.value.rings.length)continue;else{let angleA=neighbourA.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120)),angleB=neighbourB.position.getRotateAwayFromAngle(vertexA.position,vertexB.position,MathHelper.toRad(120));this.rotateSubtree(neighbourA.id,vertexB.id,angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,angleB,vertexB.position);let newTotalOverlapScore=this.getOverlapScore().total;newTotalOverlapScore>this.totalOverlapScore?(this.rotateSubtree(neighbourA.id,vertexB.id,-angleA,vertexB.position),this.rotateSubtree(neighbourB.id,vertexB.id,-angleB,vertexB.position)):this.totalOverlapScore=newTotalOverlapScore}}overlapScore=this.getOverlapScore()}}}this.resolveSecondaryOverlaps(overlapScore.scores),this.opts.isomeric&&this.annotateStereochemistry(),this.opts.compactDrawing&&"default"===this.opts.atomVisualization&&this.initPseudoElements(),this.rotateDrawing()}initRings(){let openBonds=new Map;for(let i=this.graph.vertices.length-1,vertex;0<=i;i--)if(vertex=this.graph.vertices[i],0!==vertex.value.ringbonds.length)for(let j=0;jneighbour.value.rings.length&&!neighbour.value.bridgedRing||neighbour.value.bridgedRing&&2>neighbour.value.originalRings.length)&&(vertex.value.isDrawn=!1)}}getBridgedRingRings(ringId){let involvedRings=[],that=this,recurse=function(r){let ring=that.getRing(r);involvedRings.push(r);for(let i=0,n;imaxSize&&(maxSize=size,largestCommonRing=ring)}return largestCommonRing}getVerticesAt(position,radius,excludeVertexId){let locals=[];for(let i=0,vertex;ii;){let a=this.graph.vertices[i],b=this.graph.vertices[j];if(!a.value.isDrawn||!b.value.isDrawn)continue;let dist=Vector2.subtract(a.position,b.position).lengthSq();if(disttotalSideCount[1]?0:1,sideCount:sideCount,position:sideCount[0]>sideCount[1]?0:1,anCount:anCount,bnCount:bnCount}}setRingCenter(ring){let ringSize=ring.getSize(),total=new Vector2(0,0);for(let i=0;is.sideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.sideCount[0]s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if(s.totalSideCount[0]<=s.totalSideCount[1]){normals[0].multiplyScalar(that.opts.bondSpacing),normals[1].multiplyScalar(that.opts.bondSpacing);let line=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));line.shorten(this.opts.bondLength-this.opts.shortBondLength*this.opts.bondLength),this.canvasWrapper.drawLine(line),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}}else if("#"===edge.bondType){normals[0].multiplyScalar(that.opts.bondSpacing/1.5),normals[1].multiplyScalar(that.opts.bondSpacing/1.5);let lineA=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)),lineB=new Line(Vector2.add(a,normals[1]),Vector2.add(b,normals[1]),elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay));this.canvasWrapper.drawLine(lineA),this.canvasWrapper.drawLine(lineB),this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,!1,!1,this.isDrawDecayPoint(edge.isDecay)))}else if("."===edge.bondType);else{let isChiralCenterA=vertexA.value.isStereoCenter,isChiralCenterB=vertexB.value.isStereoCenter;"up"===edge.wedge?this.canvasWrapper.drawWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):"down"===edge.wedge?this.canvasWrapper.drawDashedWedge(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay))):this.canvasWrapper.drawLine(new Line(a,b,elementA,elementB,isChiralCenterA,isChiralCenterB,this.isDrawDecayPoint(edge.isDecay)))}if(debug){let midpoint=Vector2.midpoint(a,b);this.canvasWrapper.drawDebugText(midpoint.x,midpoint.y,"e: "+edgeId)}}drawVertices(debug){for(let i=0;i_Mathabs(_MathPI-angle)&&this.canvasWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);this.canvasWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else;}if(this.opts.debug)for(let i=0,center;iring.rings.length)&&(vertex.angle=a,vertex.positioned=!0)},startVertexId,previousVertex?previousVertex.id:null);ring.positioned=!0,ring.center=center;for(let i=0,neighbour;iVector2.subtract(center,normals[0]).lengthSq()&&(nextCenter=normals[1]);let posA=Vector2.subtract(vertexA.position,nextCenter),posB=Vector2.subtract(vertexB.position,nextCenter);-1===posA.clockwise(posB)?!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexA,vertexB):!neighbour.positioned&&this.createRing(neighbour,nextCenter,vertexB,vertexA)}else if(1===vertices.length){ring.isSpiro=!0,neighbour.isSpiro=!0;let vertexA=this.graph.vertices[vertices[0]],nextCenter=Vector2.subtract(center,vertexA.position);nextCenter.invert(),nextCenter.normalize();let r=MathHelper.polyCircumradius(this.opts.bondLength,neighbour.getSize());nextCenter.multiplyScalar(r),nextCenter.add(vertexA.position),neighbour.positioned||this.createRing(neighbour,nextCenter,vertexA)}}for(let i=0;ithat.opts.overlapSensitivity&&(score+=s,count++);let position=that.graph.vertices[vertex.id].position.clone();position.multiplyScalar(s),center.add(position)}}),center.divide(score),{value:score/count,center:center}}getCurrentCenterOfMass(){let total=new Vector2(0,0),count=0;for(let i=0,vertex;itotal&&(this.rotateSubtree(a.id,overlap.common.id,2*angle,overlap.common.position),this.rotateSubtree(b.id,overlap.common.id,-2*angle,overlap.common.position))}else 1!==overlap.vertices.length||2!==overlap.rings.length}resolveSecondaryOverlaps(scores){for(let i=0;ithis.opts.overlapSensitivity){let vertex=this.graph.vertices[scores[i].id];if(vertex.isTerminal()){let closest=this.getClosestVertex(vertex);if(closest){let closestPosition=null;closestPosition=closest.isTerminal()?0===closest.id?this.graph.vertices[1].position:closest.previousPosition:0===closest.id?this.graph.vertices[1].position:closest.position;let vertexPreviousPosition=0===vertex.id?this.graph.vertices[1].position:vertex.previousPosition;vertex.position.rotateAwayFrom(closestPosition,vertexPreviousPosition,MathHelper.toRad(20))}}}}getLastVertexWithAngle(vertexId){let angle=0,vertex=null;for(;!angle&&vertexId;)vertex=this.graph.vertices[vertexId],angle=vertex.angle,vertexId=vertex.parentVertexId;return vertex}createNextBond(vertex,previousVertex=null,angle=0,originShortest=!1,skipPositioning=!1){if(vertex.positioned&&!skipPositioning)return;let doubleBondConfigSet=!1;if(previousVertex){let edge=this.graph.getEdge(vertex.id,previousVertex.id);("/"===edge.bondType||"\\"===edge.bondType)&&1==++this.doubleBondConfigCount%2&&null===this.doubleBondConfig&&(this.doubleBondConfig=edge.bondType,doubleBondConfigSet=!0,null===previousVertex.parentVertexId&&vertex.value.branchBond&&("/"===this.doubleBondConfig?this.doubleBondConfig="\\":"\\"===this.doubleBondConfig&&(this.doubleBondConfig="/")))}if(!skipPositioning)if(!previousVertex){let dummy=new Vector2(this.opts.bondLength,0);dummy.rotate(MathHelper.toRad(-60)),vertex.previousPosition=dummy,vertex.setPosition(this.opts.bondLength,0),vertex.angle=MathHelper.toRad(-60),null===vertex.value.bridgedRing&&(vertex.positioned=!0)}else if(0a?_Mathmax2(-1.0472,a):1.0472;else if(!a){let v=this.getLastVertexWithAngle(vertex.id);a=v.angle,a||(a=1.0472)}if(previousVertex&&!doubleBondConfigSet){let bondType=this.graph.getEdge(vertex.id,nextVertex.id).bondType;"/"===bondType?("/"===this.doubleBondConfig||"\\"===this.doubleBondConfig&&(a=-a),this.doubleBondConfig=null):"\\"===bondType&&("/"===this.doubleBondConfig?a=-a:"\\"===this.doubleBondConfig,this.doubleBondConfig=null)}nextVertex.angle=originShortest?a:-a,this.createNextBond(nextVertex,vertex,previousAngle+nextVertex.angle)}}else if(2===neighbours.length){let a=vertex.angle;a||(a=1.0472);let subTreeDepthA=this.graph.getTreeDepth(neighbours[0],vertex.id),subTreeDepthB=this.graph.getTreeDepth(neighbours[1],vertex.id),l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]];l.value.subtreeDepth=subTreeDepthA,r.value.subtreeDepth=subTreeDepthB;let subTreeDepthC=this.graph.getTreeDepth(previousVertex?previousVertex.id:null,vertex.id);previousVertex&&(previousVertex.value.subtreeDepth=subTreeDepthC);let cis=0,trans=1;"C"===r.value.element&&"C"!==l.value.element&&1subTreeDepthA?(cis=1,trans=0):"C"!==r.value.element&&"C"===l.value.element&&1subTreeDepthB?(cis=0,trans=1):subTreeDepthB>subTreeDepthA&&(cis=1,trans=0);let cisVertex=this.graph.vertices[neighbours[cis]],transVertex=this.graph.vertices[neighbours[trans]],originShortest=!1;subTreeDepthCd1&&d2>d3?(s=this.graph.vertices[neighbours[1]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[2]]):d3>d1&&d3>d2&&(s=this.graph.vertices[neighbours[2]],l=this.graph.vertices[neighbours[0]],r=this.graph.vertices[neighbours[1]]),previousVertex&&1>previousVertex.value.rings.length&&1>s.value.rings.length&&1>l.value.rings.length&&1>r.value.rings.length&&1===this.graph.getTreeDepth(l.id,vertex.id)&&1===this.graph.getTreeDepth(r.id,vertex.id)&&1d1&&d2>d3&&d2>d4?(w=this.graph.vertices[neighbours[1]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[2]],z=this.graph.vertices[neighbours[3]]):d3>d1&&d3>d2&&d3>d4?(w=this.graph.vertices[neighbours[2]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[3]]):d4>d1&&d4>d2&&d4>d3&&(w=this.graph.vertices[neighbours[3]],x=this.graph.vertices[neighbours[0]],y=this.graph.vertices[neighbours[1]],z=this.graph.vertices[neighbours[2]]),w.angle=-MathHelper.toRad(36),x.angle=MathHelper.toRad(36),y.angle=-MathHelper.toRad(108),z.angle=MathHelper.toRad(108),this.createNextBond(w,vertex,previousAngle+w.angle),this.createNextBond(x,vertex,previousAngle+x.angle),this.createNextBond(y,vertex,previousAngle+y.angle),this.createNextBond(z,vertex,previousAngle+z.angle)}}}getCommonRingbondNeighbour(vertex){let neighbours=vertex.neighbours;for(let i=0,neighbour;imaxLevels&&(maxLevels=priorities[j][1].length);for(let k=0;kmaxEntries&&(maxEntries=priorities[j][1][k].length)}for(let j=0,diff;jb[1][j][k])return-1;if(a[1][j][k]b[0]?-1:a[0]vertex.getNeighbourCount()||0heteroAtomCount)continue;let previous=null;for(let j=0,neighbour;jr.x+this.opts.mouseTolerance)&&(mouseY>l.y-this.opts.mouseTolerance&&mouseYr.y-this.opts.mouseTolerance&&mouseY{e.setDecay(!1)}),this.decays.forEach(e=>{this.edges[e].setDecay(!0)})}standardDecays(){for(let i=0;i{this.edges[e].setDecay(!0),this.edges[e].setDecayAll(!0),this.decays.push(e),this.decaysAll.push(e)})}isDecayPoint(sourceId,targetId,edgeBondId,decayTypes=DecayPoint.VALUES.ALL){switch(decayTypes){case DecayPoint.VALUES.ALL:let found=this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);return!1===found?this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId):found;case DecayPoint.VALUES.COO:return this.getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId);case DecayPoint.VALUES.CONH:return this.getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId);}}getNeighbourEdgeDecayIdOfCOO(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"O",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"O",edgeBondId)}getNeighbourEdgeDecayIdOfCONH(sourceId,targetId,edgeBondId){if("O"===this.vertices[sourceId].value.element&&"C"===this.vertices[targetId].value.element)return this.getNeighbourEdgeDecayId(targetId,"N",edgeBondId);return!("O"!==this.vertices[targetId].value.element||"C"!==this.vertices[sourceId].value.element)&&this.getNeighbourEdgeDecayId(sourceId,"N",edgeBondId)}getNeighbourEdgeDecayId(vertexId,element,edgeBondId){for(let i=0,edgeId;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getSubgraphDistanceMatrix(vertexIds){let length=vertexIds.length,adja=this.getSubgraphAdjacencyMatrix(vertexIds),dist=Array(length);for(var i=0;idist[i][k]+dist[k][j]&&(dist[i][j]=dist[i][k]+dist[k][j]);return dist}getAdjacencyList(){let length=this.vertices.length,adjacencyList=Array(length);for(var i=0;imax&&(max=d)}return max+1}traverseTree(vertexId,parentVertexId,callback,maxDepth=999999,ignoreFirst=!1,depth=1,visited=null){if(null===visited&&(visited=new Uint8Array(this.vertices.length)),depth>maxDepth+1||1===visited[vertexId])return;visited[vertexId]=1;let vertex=this.vertices[vertexId],neighbours=vertex.getNeighbours(parentVertexId);(!ignoreFirst||1maxEnergy&&!1===arrPositioned[i]&&(maxEnergy=delta,maxEnergyId=i,maxDEX=dEX,maxDEY=dEY)}return[maxEnergyId,maxEnergy,maxDEX,maxDEY]},update=function(index,dEX,dEY){let dxx=0,dyy=0,dxy=0,ux=arrPositionX[index],uy=arrPositionY[index],arrL=matLength[index],arrK=matStrength[index];for(i=length;i--;){if(i===index)continue;let vx=arrPositionX[i],vy=arrPositionY[i],l=arrL[i],k=arrK[i],m=(ux-vx)*(ux-vx),denom=1/_Mathpow(m+(uy-vy)*(uy-vy),1.5);dxx+=k*(1-l*(uy-vy)*(uy-vy)*denom),dyy+=k*(1-l*m*denom),dxy+=k*(l*(ux-vx)*(uy-vy)*denom)}0==dxx&&(dxx=.1),0===dyy&&(dyy=.1),0===dxy&&(dxy=.1);let dy=dEX/dxx+dEY/dxy;dy/=dxy/dxx-dyy/dxy;let dx=-(dxy*dy+dEX)/dxx;arrPositionX[index]+=dx,arrPositionY[index]+=dy;let arrE=matEnergy[index];dEX=0,dEY=0,ux=arrPositionX[index],uy=arrPositionY[index];let vx,vy,prevEx,prevEy,denom;for(i=length;i--;)index!==i&&(vx=arrPositionX[i],vy=arrPositionY[i],prevEx=arrE[i][0],prevEy=arrE[i][1],denom=1/_Mathsqrt2((ux-vx)*(ux-vx)+(uy-vy)*(uy-vy)),dx=arrK[i]*(ux-vx-arrL[i]*(ux-vx)*denom),dy=arrK[i]*(uy-vy-arrL[i]*(uy-vy)*denom),arrE[i]=[dx,dy],dEX+=dx,dEY+=dy,arrEnergySumX[i]+=dx-prevEx,arrEnergySumY[i]+=dy-prevEy);arrEnergySumX[index]=dEX,arrEnergySumY[index]=dEY},maxEnergyId=0,dEX=0,dEY=0,delta=0,iteration=0,innerIteration=0;for(;maxEnergy>threshold&&maxIteration>iteration;)for(iteration++,[maxEnergyId,maxEnergy,dEX,dEY]=highestEnergy(),delta=maxEnergy,innerIteration=0;delta>innerThreshold&&maxInnerIteration>innerIteration;)innerIteration++,update(maxEnergyId,dEX,dEY),[delta,dEX,dEY]=energy(maxEnergyId);for(i=length;i--;){let index=vertexIds[i],vertex=this.vertices[index];vertex.position.x=arrPositionX[i],vertex.position.y=arrPositionY[i],vertex.positioned=!0,vertex.forcePositioned=!0}}_bridgeDfs(u,visited,disc,low,parent,adj,outBridges){visited[u]=!0,disc[u]=low[u]=++this._time;for(var i=0;idisc[u]&&outBridges.push([u,v]))}}static getConnectedComponents(adjacencyMatrix){let length=adjacencyMatrix.length,visited=Array(length),components=[],count=0;visited.fill(!1);for(var u=0;u=sequence.length)return{sequence:sequence,smiles:smiles};for(char=sequence.charAt(position);!isNaN(char);){if(number+=char,++position,position>=sequence.length)return{sequence:sequence,smiles:smiles};char=sequence.charAt(position)}let j;for(j=0;j=sequence.length)break;char=sequence.charAt(position)}return{sequence:newSequence,smiles:newSmiles}}getSequencePermutation(sequence){let match=null,permutation=[];for(;null!=(match=/\d+/g.exec(sequence));)permutation.push(match);return permutation}dfsSmallStart(){this._smallGraph=new SmallGraph;for(let index=0;indexdecaysCounter.getValue()&&!0===isPolyketide.getValue()&&isPolyketide.setValue(through.every(vertex=>"O"===vertex||"N"===vertex)&&4this.vertices[lastVertexId].digits.includes(e))&&(vertex.digits.push(this._digitCounter),this.vertices[lastVertexId].digits.push(this._digitCounter),this._digitCounter++)),vertex.vertexState===VertexState.VALUES.NOT_FOUND)&&"H"!==vertex.value.element){this.first===vertex.id&&"C"===vertex.value.element&&isPolyketide.getValue()&&(stackSmiles.push("O"),isPolyketide.setValue(!1)),vertex.value.bracket?(stackSmiles.push("["),Graph.printVertexValue(stackSmiles,vertex),0vertex.value.bracket.charge&&stackSmiles.push(vertex.value.bracket.charge),stackSmiles.push("]")):Graph.printVertexValue(stackSmiles,vertex),vertexCounter.increment(),isSecondPass&&stackSmiles.push(this.smilesNumbersAdd(vertex)),this._markComponent||this._startingVertexes.push(vertex),vertex.component=this._cnt,this._markComponent=!0,vertex.vertexState=VertexState.VALUES.OPEN;for(let i=0;i=smiles.length)););index--,numbers.add(num)}return numbers}static findFirst(smiles,number){return smiles.indexOf(number)}static findSecond(smiles,from,number){let result=smiles.indexOf(number,from);if(-1===result)throw"Not Found";return result}smilesNumbersAdd(vertex){let numbers="";for(let i=0,num;ie===num)){let nextVertex=this.vertices.find(e=>e.digits.includes(num)&&e.id!==vertex.id),intersection=vertex.edges.filter(element=>nextVertex.edges.includes(element));if(0peg$maxFailPos&&(peg$maxFailPos=peg$currPos,peg$maxFailExpected=[]),peg$maxFailExpected.push(expected))}function peg$buildSimpleError(message,location){return new peg$SyntaxError(message,null,null,location)}function peg$parsechain(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;if(s0=peg$currPos,s1=peg$currPos,s2=peg$parseatom(),s2!==peg$FAILED){for(s3=[],s4=peg$parsebranch();s4!==peg$FAILED;)s3.push(s4),s4=peg$parsebranch();if(s3!==peg$FAILED){for(s4=[],s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));s5!==peg$FAILED;)s4.push(s5),s5=peg$currPos,s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s7=peg$parsering(),s7===peg$FAILED?(peg$currPos=s5,s5=peg$FAILED):(s6=[s6,s7],s5=s6));if(s4!==peg$FAILED){for(s5=[],s6=peg$parsebranch();s6!==peg$FAILED;)s5.push(s6),s6=peg$parsebranch();if(s5===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s6=peg$parsebond(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED)peg$currPos=s1,s1=peg$FAILED;else if(s7=peg$parsechain(),s7===peg$FAILED&&(s7=null),s7!==peg$FAILED){for(s8=[],s9=peg$parsebranch();s9!==peg$FAILED;)s8.push(s9),s9=peg$parsebranch();s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8],s1=s2)}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c0(s1)),s0=s1,s0}function peg$parsebranch(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,40===input.charCodeAt(peg$currPos)?(s2="(",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c2)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parsebond(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s4=peg$parsechain(),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(41===input.charCodeAt(peg$currPos)?(s5=")",peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c4)),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5],s1=s2)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c5(s1)),s0=s1,s0}function peg$parseatom(){var s0,s1;return s0=peg$currPos,s1=peg$parseorganicsymbol(),s1===peg$FAILED&&(s1=peg$parsearomaticsymbol(),s1===peg$FAILED&&(s1=peg$parsebracketatom(),s1===peg$FAILED&&(s1=peg$parsewildcard()))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsebond(){var s0,s1;if(s0=peg$currPos,peg$c7.test(input.charAt(peg$currPos))){if(s1=input.charAt(peg$currPos),s1===input.charAt(peg$currPos+1))throw s1=peg$FAILED,peg$buildSimpleError("The parser encountered a bond repetition.",peg$currPos+1);peg$currPos++}else s1=peg$FAILED,peg$fail(peg$c8);return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c9(s1)),s0=s1,s0}function peg$parsebracketatom(){var s0,s1,s2,s3,s4,s5,s6,s7,s8,s9;return s0=peg$currPos,s1=peg$currPos,91===input.charCodeAt(peg$currPos)?(s2="[",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c11)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s3=peg$parseisotope(),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):("se"===input.substr(peg$currPos,2)?(s4="se",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c13)),s4===peg$FAILED&&("as"===input.substr(peg$currPos,2)?(s4="as",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c15)),s4===peg$FAILED&&(s4=peg$parsearomaticsymbol(),s4===peg$FAILED&&(s4=peg$parseelementsymbol(),s4===peg$FAILED&&(s4=peg$parsewildcard())))),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s5=peg$parsechiral(),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s6=peg$parsehcount(),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s7=peg$parsecharge(),s7===peg$FAILED&&(s7=null),s7===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s8=peg$parseclass(),s8===peg$FAILED&&(s8=null),s8===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(93===input.charCodeAt(peg$currPos)?(s9="]",peg$currPos++):(s9=peg$FAILED,peg$fail(peg$c17)),s9===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4,s5,s6,s7,s8,s9],s1=s2)))))))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c18(s1)),s0=s1,s0}function peg$parseorganicsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,66===input.charCodeAt(peg$currPos)?(s2="B",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c20)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(114===input.charCodeAt(peg$currPos)?(s3="r",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c22)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(s1=peg$currPos,67===input.charCodeAt(peg$currPos)?(s2="C",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c24)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(108===input.charCodeAt(peg$currPos)?(s3="l",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c26)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1===peg$FAILED&&(peg$c27.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c28)))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c29(s1)),s0=s1,s0}function peg$parsearomaticsymbol(){var s0,s1;return s0=peg$currPos,peg$c30.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c31)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c6(s1)),s0=s1,s0}function peg$parsewildcard(){var s0,s1;return s0=peg$currPos,42===input.charCodeAt(peg$currPos)?(s1="*",peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c33)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c34(s1)),s0=s1,s0}function peg$parseelementsymbol(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,peg$c35.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c36)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c37.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c38)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c39(s1)),s0=s1,s0}function peg$parsering(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,37===input.charCodeAt(peg$currPos)?(s2="%",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c41)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c43)),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1===peg$FAILED&&(peg$c44.test(input.charAt(peg$currPos))?(s1=input.charAt(peg$currPos),peg$currPos++):(s1=peg$FAILED,peg$fail(peg$c45))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c46(s1)),s0=s1,s0}function peg$parsechiral(){var s0,s1,s2,s3,s4,s5,s6;return s0=peg$currPos,s1=peg$currPos,64===input.charCodeAt(peg$currPos)?(s2="@",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c48)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(64===input.charCodeAt(peg$currPos)?(s3="@",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c48)),s3===peg$FAILED&&(s3=peg$currPos,"TH"===input.substr(peg$currPos,2)?(s4="TH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c50)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"AL"===input.substr(peg$currPos,2)?(s4="AL",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c54)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c51.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c52)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"SP"===input.substr(peg$currPos,2)?(s4="SP",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c56)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c57.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c58)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)),s3===peg$FAILED&&(s3=peg$currPos,"TB"===input.substr(peg$currPos,2)?(s4="TB",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c60)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4))),s3===peg$FAILED&&(s3=peg$currPos,"OH"===input.substr(peg$currPos,2)?(s4="OH",peg$currPos+=2):(s4=peg$FAILED,peg$fail(peg$c62)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c42.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c43)),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45)),s6===peg$FAILED&&(s6=null),s6===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5,s6],s3=s4)))))))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c63(s1)),s0=s1,s0}function peg$parsecharge(){var s0,s1;return s0=peg$currPos,s1=peg$parseposcharge(),s1===peg$FAILED&&(s1=peg$parsenegcharge()),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c64(s1)),s0=s1,s0}function peg$parseposcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,43===input.charCodeAt(peg$currPos)?(s2="+",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c66)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(43===input.charCodeAt(peg$currPos)?(s3="+",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c66)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c67(s1)),s0=s1,s0}function peg$parsenegcharge(){var s0,s1,s2,s3,s4,s5;return s0=peg$currPos,s1=peg$currPos,45===input.charCodeAt(peg$currPos)?(s2="-",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c69)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(45===input.charCodeAt(peg$currPos)?(s3="-",peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c69)),s3===peg$FAILED&&(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s5=input.charAt(peg$currPos),peg$currPos++):(s5=peg$FAILED,peg$fail(peg$c45)),s5===peg$FAILED&&(s5=null),s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4))),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c70(s1)),s0=s1,s0}function peg$parsehcount(){var s0,s1,s2,s3;return s0=peg$currPos,s1=peg$currPos,72===input.charCodeAt(peg$currPos)?(s2="H",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c72)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c73(s1)),s0=s1,s0}function peg$parseclass(){var s0,s1,s2,s3,s4,s5,s6;if(s0=peg$currPos,s1=peg$currPos,58===input.charCodeAt(peg$currPos)?(s2=":",peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c75)),s2!==peg$FAILED){if(s3=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c43)),s4!==peg$FAILED){for(s5=[],peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s6!==peg$FAILED;)s5.push(s6),peg$c44.test(input.charAt(peg$currPos))?(s6=input.charAt(peg$currPos),peg$currPos++):(s6=peg$FAILED,peg$fail(peg$c45));s5===peg$FAILED?(peg$currPos=s3,s3=peg$FAILED):(s4=[s4,s5],s3=s4)}else peg$currPos=s3,s3=peg$FAILED;s3===peg$FAILED&&(peg$c76.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c77))),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3],s1=s2)}else peg$currPos=s1,s1=peg$FAILED;return s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c78(s1)),s0=s1,s0}function peg$parseisotope(){var s0,s1,s2,s3,s4;return s0=peg$currPos,s1=peg$currPos,peg$c42.test(input.charAt(peg$currPos))?(s2=input.charAt(peg$currPos),peg$currPos++):(s2=peg$FAILED,peg$fail(peg$c43)),s2===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s3=input.charAt(peg$currPos),peg$currPos++):(s3=peg$FAILED,peg$fail(peg$c45)),s3===peg$FAILED&&(s3=null),s3===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(peg$c44.test(input.charAt(peg$currPos))?(s4=input.charAt(peg$currPos),peg$currPos++):(s4=peg$FAILED,peg$fail(peg$c45)),s4===peg$FAILED&&(s4=null),s4===peg$FAILED?(peg$currPos=s1,s1=peg$FAILED):(s2=[s2,s3,s4],s1=s2))),s1!==peg$FAILED&&(peg$savedPos=s0,s1=peg$c79(s1)),s0=s1,s0}options=void 0===options?{}:options;var nOpenParentheses=input.split("(").length-1,nCloseParentheses=input.split(")").length-1;if(nOpenParentheses!==nCloseParentheses)throw peg$buildSimpleError("The number of opening parentheses does not match the number of closing parentheses.",0);var peg$FAILED={},peg$startRuleFunctions={chain:peg$parsechain},peg$startRuleFunction=peg$parsechain,peg$c0=function(s){for(var branches=[],rings=[],i=0;imax;){let prev=current;callback(prev),current=vertices[current].getNextInRing(vertices,this.id,previousVertexId),previousVertexId=prev,current==startVertexId&&(current=null),max++}}getOrderedNeighbours(ringConnections){let orderedNeighbours=Array(this.neighbours.length);for(let i=0,vertices;inewPathLength){var l,m,n;if(previousPathLength===newPathLength+1)for(pe_prime[i][j]=[pe[i][j].length],l=pe[i][j].length;l--;)for(pe_prime[i][j][l]=[pe[i][j][l].length],m=pe[i][j][l].length;m--;)for(pe_prime[i][j][l][m]=[pe[i][j][l][m].length],n=pe[i][j][l][m].length;n--;)pe_prime[i][j][l][m][n]=[pe[i][j][l][m][0],pe[i][j][l][m][1]];else pe_prime[i][j]=[];for(d[i][j]=newPathLength,pe[i][j]=[[]],l=pe[i][k][0].length;l--;)pe[i][j][0].push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)pe[i][j][0].push(pe[k][j][0][l])}else if(previousPathLength===newPathLength){if(pe[i][k].length&&pe[k][j].length){var l;if(pe[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe[i][j][0]=tmp}}}else if(previousPathLength===newPathLength-1){var l;if(pe_prime[i][j].length){let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j].push(tmp)}else{let tmp=[];for(l=pe[i][k][0].length;l--;)tmp.push(pe[i][k][0][l]);for(l=pe[k][j][0].length;l--;)tmp.push(pe[k][j][0][l]);pe_prime[i][j][0]=tmp}}}return{d:d,pe:pe,pe_prime:pe_prime}}static getRingCandidates(d,pe,pe_prime){let length=d.length,candidates=[],c=0;for(let i=0;insssr)return cSssr}else for(let j=0,bonds;jnsssr)return cSssr}return cSssr}static getEdgeCount(adjacencyMatrix){let edgeCount=0,length=adjacencyMatrix.length;for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeCount++;return edgeCount}static getEdgeList(adjacencyMatrix){let length=adjacencyMatrix.length,edgeList=[];for(var i=length-1;i--;)for(var j=length;j--;)1===adjacencyMatrix[i][j]&&edgeList.push([i,j]);return edgeList}static bondsToAtoms(bonds){let atoms=new Set;for(var i=bonds.length;i--;)atoms.add(bonds[i][0]),atoms.add(bonds[i][1]);return atoms}static getBondCount(atoms,adjacencyMatrix){let count=0;for(let u of atoms)for(let v of atoms)u!==v&&(count+=adjacencyMatrix[u][v]);return count/2}static pathSetsContain(pathSets,pathSet,bonds,allBonds,arrBondCount,arrRingCount){for(var i=pathSets.length;i--;){if(SSSR.isSupersetOf(pathSet,pathSets[i]))return!0;if(pathSets[i].size===pathSet.size&&SSSR.areSetsEqual(pathSets[i],pathSet))return!0}let count=0,allContained=!1;for(i=bonds.length;i--;)for(var j=allBonds.length;j--;)(bonds[i][0]===allBonds[j][0]&&bonds[i][1]===allBonds[j][1]||bonds[i][1]===allBonds[j][0]&&bonds[i][0]===allBonds[j][1])&&count++,count===bonds.length&&(allContained=!0);let specialCase=!1;if(allContained)for(let element of pathSet)if(arrRingCount[element]e.vertexState=VertexState.VALUES.NOT_FOUND)}getSourceNode(){let ends=[];for(let index=0;indexthis._nodes[v].onRing=!0);continue}node.neighbours.forEach(neighbour=>{if(!path.some(e=>e===neighbour.neighbour)||neighbour.neighbour===start.id){let newPath=[...path];newPath.push(neighbour.neighbour),queue.push(newPath)}}),firstPass=!1}}sortByRingPreference(array){let sortedArray=[...array];return sortedArray.sort((a,b)=>this._nodes[a.neighbour].onRing===this._nodes[b.neighbour].onRing?a.direction>b.direction?-1:a.direction{let edges=graph.getEdges(vertex.id);for(var i=0;is.sideCount[1]||s.totalSideCount[0]>s.totalSideCount[1]){this.multiplyNormals(normals,opts.bondSpacing);let line=new Line(Vector2.add(a,normals[0]),Vector2.add(b,normals[0]),elementA,elementB);line.shorten(opts.bondLength-opts.shortBondLength*opts.bondLength),svgWrapper.drawLine(line),svgWrapper.drawLine(new Line(a,b,elementA,elementB))}else if(s.sideCount[0]_Mathabs2(_MathPI3-angle)&&svgWrapper.drawPoint(vertex.position.x,vertex.position.y,element)}if(debug){let value="v: "+vertex.id+" "+ArrayHelper.print(atom.ringbonds);svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,value)}else svgWrapper.drawDebugText(vertex.position.x,vertex.position.y,vertex.value.chirality)}if(opts.debug)for(var i=0;i {\r\n const context = canvas.getContext('2d');\r\n context.clearRect(0, 0, canvas.width, canvas.height);\r\n })\r\n};\r\n\r\n/**\r\n* Parses the entered smiles string.\r\n*\r\n* @static\r\n* @param {String} smiles A SMILES string.\r\n* @param {Function} successCallback A callback that is called on success with the parse tree.\r\n* @param {Function} errorCallback A callback that is called with the error object on error.\r\n*/\r\nSmilesDrawer.parse = function(smiles, successCallback, errorCallback) {\r\n try {\r\n if (successCallback) {\r\n successCallback(Parser.parse(smiles));\r\n }\r\n } catch (err) {\r\n if (errorCallback) {\r\n errorCallback(err);\r\n }\r\n }\r\n};\r\n\r\nif (canUseDOM) {\r\n window.SmilesDrawer = SmilesDrawer;\r\n}\r\n\r\n// There be dragons (polyfills)\r\n\r\nif (!Array.prototype.fill) {\r\nObject.defineProperty(Array.prototype, 'fill', {\r\n value: function(value) {\r\n\r\n // Steps 1-2.\r\n if (this == null) {\r\n throw new TypeError('this is null or not defined');\r\n }\r\n\r\n var O = Object(this);\r\n\r\n // Steps 3-5.\r\n var len = O.length >>> 0;\r\n\r\n // Steps 6-7.\r\n var start = arguments[1];\r\n var relativeStart = start >> 0;\r\n\r\n // Step 8.\r\n var k = relativeStart < 0 ?\r\n Math.max(len + relativeStart, 0) :\r\n Math.min(relativeStart, len);\r\n\r\n // Steps 9-10.\r\n var end = arguments[2];\r\n var relativeEnd = end === undefined ?\r\n len : end >> 0;\r\n\r\n // Step 11.\r\n var final = relativeEnd < 0 ?\r\n Math.max(len + relativeEnd, 0) :\r\n Math.min(relativeEnd, len);\r\n\r\n // Step 12.\r\n while (k < final) {\r\n O[k] = value;\r\n k++;\r\n }\r\n\r\n // Step 13.\r\n return O;\r\n }\r\n});\r\n}\r\n\r\nmodule.exports = SmilesDrawer;","//@ts-check\r\n\r\n/** \r\n * A static class containing helper functions for array-related tasks. \r\n */\r\nclass ArrayHelper {\r\n /**\r\n * Clone an array or an object. If an object is passed, a shallow clone will be created.\r\n *\r\n * @static\r\n * @param {*} arr The array or object to be cloned.\r\n * @returns {*} A clone of the array or object.\r\n */\r\n static clone(arr) {\r\n let out = Array.isArray(arr) ? Array() : {};\r\n \r\n for (let key in arr) {\r\n let value = arr[key];\r\n \r\n if (typeof value.clone === 'function') {\r\n out[key] = value.clone();\r\n }\r\n else {\r\n out[key] = (typeof value === 'object') ? ArrayHelper.clone(value) : value;\r\n }\r\n }\r\n \r\n return out;\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not the two arrays contain the same elements.\r\n * Only supports 1d, non-nested arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not the two arrays contain the same elements.\r\n */\r\n static equals(arrA, arrB) {\r\n if (arrA.length !== arrB.length) {\r\n return false;\r\n }\r\n\r\n let tmpA = arrA.slice().sort();\r\n let tmpB = arrB.slice().sort();\r\n\r\n for (let i = 0; i < tmpA.length; i++) {\r\n if (tmpA[i] !== tmpB[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns a string representation of an array. If the array contains objects with an id property, the id property is printed for each of the elements.\r\n *\r\n * @static\r\n * @param {Object[]} arr An array.\r\n * @param {*} arr[].id If the array contains an object with the property 'id', the properties value is printed. Else, the array elements value is printend.\r\n * @returns {String} A string representation of the array.\r\n */\r\n static print(arr) {\r\n if (arr.length == 0) {\r\n return '';\r\n }\r\n\r\n let s = '(';\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n s += arr[i].id ? arr[i].id + ', ' : arr[i] + ', ';\r\n }\r\n\r\n s = s.substring(0, s.length - 2);\r\n\r\n return s + ')';\r\n }\r\n\r\n /**\r\n * Run a function for each element in the array. The element is supplied as an argument for the callback function\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Function} callback The callback function that is called for each element.\r\n */\r\n static each(arr, callback) {\r\n for (let i = 0; i < arr.length; i++) {\r\n callback(arr[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Return the array element from an array containing objects, where a property of the object is set to a given value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {(String|Number)} property A property contained within an object in the array.\r\n * @param {(String|Number)} value The value of the property.\r\n * @returns {*} The array element matching the value.\r\n */\r\n static get(arr, property, value) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][property] == value) {\r\n return arr[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains a given value. the options object passed as a second argument can contain three properties. value: The value to be searched for. property: The property that is to be searched for a given value. func: A function that is used as a callback to return either true or false in order to do a custom comparison.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Object} options See method description.\r\n * @param {*} options.value The value for which to check.\r\n * @param {String} [options.property=undefined] The property on which to check.\r\n * @param {Function} [options.func=undefined] A custom property function.\r\n * @returns {Boolean} A boolean whether or not the array contains a value.\r\n */\r\n static contains(arr, options) {\r\n if (!options.property && !options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] == options.value) {\r\n return true;\r\n }\r\n }\r\n } else if (options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (options.func(arr[i])) {\r\n return true;\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][options.property] == options.value) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array containing the intersection between two arrays. That is, values that are common to both arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The intersecting vlaues.\r\n */\r\n static intersection(arrA, arrB) {\r\n let intersection = [];\r\n \r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n intersection.push(arrA[i]);\r\n }\r\n }\r\n }\r\n\r\n return intersection;\r\n }\r\n\r\n /**\r\n * Returns an array of unique elements contained in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @returns {Array} An array of unique elements contained within the array supplied as an argument.\r\n */\r\n static unique(arr) {\r\n let contains = {};\r\n return arr.filter(function (i) {\r\n // using !== instead of hasOwnProperty (http://andrew.hedges.name/experiments/in/)\r\n return contains[i] !== undefined ? false : (contains[i] = true);\r\n });\r\n }\r\n\r\n /**\r\n * Count the number of occurences of a value in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be counted.\r\n * @returns {Number} The number of occurences of a value in the array.\r\n */\r\n static count(arr, value) {\r\n let count = 0;\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] === value) {\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Toggles the value of an array. If a value is not contained in an array, the array returned will contain all the values of the original array including the value. If a value is contained in an array, the array returned will contain all the values of the original array excluding the value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be toggled.\r\n * @returns {Array} The toggled array.\r\n */\r\n static toggle(arr, value) {\r\n let newArr = Array();\r\n\r\n let removed = false;\r\n for (let i = 0; i < arr.length; i++) {\r\n // Do not copy value if it exists\r\n if (arr[i] !== value) {\r\n newArr.push(arr[i]);\r\n } else {\r\n // The element was not copied to the new array, which\r\n // means it was removed\r\n removed = true;\r\n }\r\n }\r\n\r\n // If the element was not removed, then it was not in the array\r\n // so add it\r\n if (!removed) {\r\n newArr.push(value);\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n /**\r\n * Remove a value from an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} A new array with the element with a given value removed.\r\n */\r\n static remove(arr, value) {\r\n let tmp = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] !== value) {\r\n tmp.push(arr[i]);\r\n }\r\n }\r\n\r\n return tmp;\r\n }\r\n\r\n /**\r\n * Remove a value from an array with unique values.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} An array with the element with a given value removed.\r\n */\r\n static removeUnique(arr, value) {\r\n let index = arr.indexOf(value);\r\n\r\n if (index > -1) {\r\n arr.splice(index, 1);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Remove all elements contained in one array from another array.\r\n *\r\n * @static\r\n * @param {Array} arrA The array to be filtered.\r\n * @param {Array} arrB The array containing elements that will be removed from the other array.\r\n * @returns {Array} The filtered array.\r\n */\r\n static removeAll(arrA, arrB) {\r\n return arrA.filter(function (item) {\r\n return arrB.indexOf(item) === -1;\r\n });\r\n }\r\n\r\n /**\r\n * Merges two arrays and returns the result. The first array will be appended to the second array.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The merged array.\r\n */\r\n static merge(arrA, arrB) {\r\n let arr = new Array(arrA.length + arrB.length);\r\n\r\n for (let i = 0; i < arrA.length; i++) {\r\n arr[i] = arrA[i];\r\n }\r\n\r\n for (let i = 0; i < arrB.length; i++) {\r\n arr[arrA.length + i] = arrB[i];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains all the elements of another array, without regard to the order.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not both array contain the same elements.\r\n */\r\n static containsAll(arrA, arrB) {\r\n let containing = 0;\r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n containing++;\r\n }\r\n }\r\n }\r\n\r\n return containing === arrB.length;\r\n }\r\n \r\n /**\r\n * Sort an array of atomic number information. Where the number is indicated as x, x.y, x.y.z, ...\r\n *\r\n * @param {Object[]} arr An array of vertex ids with their associated atomic numbers.\r\n * @param {Number} arr[].vertexId A vertex id.\r\n * @param {String} arr[].atomicNumber The atomic number associated with the vertex id.\r\n * @returns {Object[]} The array sorted by atomic number. Example of an array entry: { atomicNumber: 2, vertexId: 5 }.\r\n */\r\n static sortByAtomicNumberDesc(arr) {\r\n let map = arr.map(function(e, i) {\r\n return { index: i, value: e.atomicNumber.split('.').map(Number) };\r\n });\r\n\r\n map.sort(function(a, b) {\r\n let min = Math.min(b.value.length, a.value.length);\r\n let i = 0;\r\n \r\n while(i < min && b.value[i] === a.value[i]) {\r\n i++;\r\n }\r\n\r\n return i === min ? b.value.length - a.value.length : b.value[i] - a.value[i];\r\n });\r\n\r\n return map.map(function(e) {\r\n return arr[e.index];\r\n });\r\n }\r\n\r\n /**\r\n * Copies a an n-dimensional array.\r\n * \r\n * @param {Array} arr The array to be copied.\r\n * @returns {Array} The copy.\r\n */\r\n static deepCopy(arr) {\r\n let newArr = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n let item = arr[i];\r\n\r\n if (item instanceof Array) {\r\n newArr[i] = ArrayHelper.deepCopy(item);\r\n } else {\r\n newArr[i] = item;\r\n }\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = ArrayHelper;","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper');\r\n\r\n/** \r\n * A class representing an atom.\r\n * \r\n * @property {String} element The element symbol of this atom. Single-letter symbols are always uppercase. Examples: H, C, F, Br, Si, ...\r\n * @property {Boolean} drawExplicit A boolean indicating whether or not this atom is drawn explicitly (for example, a carbon atom). This overrides the default behaviour.\r\n * @property {Object[]} ringbonds An array containing the ringbond ids and bond types as specified in the original SMILE.\r\n * @property {String} branchBond The branch bond as defined in the SMILES.\r\n * @property {Number} ringbonds[].id The ringbond id as defined in the SMILES.\r\n * @property {String} ringbonds[].bondType The bond type of the ringbond as defined in the SMILES.\r\n * @property {Number[]} rings The ids of rings which contain this atom.\r\n * @property {String} bondType The bond type associated with this array. Examples: -, =, #, ...\r\n * @property {Boolean} isBridge A boolean indicating whether or not this atom is part of a bridge in a bridged ring (contained by the largest ring).\r\n * @property {Boolean} isBridgeNode A boolean indicating whether or not this atom is a bridge node (a member of the largest ring in a bridged ring which is connected to a bridge-atom).\r\n * @property {Number[]} originalRings Used to back up rings when they are replaced by a bridged ring.\r\n * @property {Number} bridgedRing The id of the bridged ring if the atom is part of a bridged ring.\r\n * @property {Number[]} anchoredRings The ids of the rings that are anchored to this atom. The centers of anchored rings are translated when this atom is translated.\r\n * @property {Object} bracket If this atom is defined as a bracket atom in the original SMILES, this object contains all the bracket information. Example: { hcount: {Number}, charge: ['--', '-', '+', '++'], isotope: {Number} }.\r\n * @property {Number} plane Specifies on which \"plane\" the atoms is in stereochemical deptictions (-1 back, 0 middle, 1 front).\r\n * @property {Object[]} attachedPseudoElements A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @property {String} attachedPseudoElement[].element The element symbol.\r\n * @property {Number} attachedPseudoElement[].count The number of occurences that match the key.\r\n * @property {Number} attachedPseudoElement[].hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n * @property {Boolean} hasAttachedPseudoElements A boolean indicating whether or not this attom will be drawn with an attached pseudo element or concatinated elements.\r\n * @property {Boolean} isDrawn A boolean indicating whether or not this atom is drawn. In contrast to drawExplicit, the bond is drawn neither.\r\n * @property {Boolean} isConnectedToRing A boolean indicating whether or not this atom is directly connected (but not a member of) a ring.\r\n * @property {String[]} neighbouringElements An array containing the element symbols of neighbouring atoms.\r\n * @property {Boolean} isPartOfAromaticRing A boolean indicating whether or not this atom is part of an explicitly defined aromatic ring. Example: c1ccccc1.\r\n * @property {Number} bondCount The number of bonds in which this atom is participating.\r\n * @property {String} chirality The chirality of this atom if it is a stereocenter (R or S).\r\n * @property {Number} priority The priority of this atom acording to the CIP rules, where 0 is the highest priority.\r\n * @property {Boolean} mainChain A boolean indicating whether or not this atom is part of the main chain (used for chirality).\r\n * @property {String} hydrogenDirection The direction of the hydrogen, either up or down. Only for stereocenters with and explicit hydrogen.\r\n * @property {Number} subtreeDepth The depth of the subtree coming from a stereocenter.\r\n */\r\nclass Atom {\r\n /**\r\n * The constructor of the class Atom.\r\n *\r\n * @param {String} element The one-letter code of the element.\r\n * @param {String} [bondType='-'] The type of the bond associated with this atom.\r\n */\r\n constructor(element, bondType = '-') {\r\n this.element = element.length === 1 ? element.toUpperCase() : element;\r\n this.drawExplicit = false;\r\n this.ringbonds = Array();\r\n this.rings = Array();\r\n this.bondType = bondType;\r\n this.branchBond = null;\r\n this.isBridge = false;\r\n this.isBridgeNode = false;\r\n this.originalRings = Array();\r\n this.bridgedRing = null;\r\n this.anchoredRings = Array();\r\n this.bracket = null;\r\n this.plane = 0;\r\n this.attachedPseudoElements = {};\r\n this.hasAttachedPseudoElements = false;\r\n this.isDrawn = true;\r\n this.isConnectedToRing = false;\r\n this.neighbouringElements = Array();\r\n this.isPartOfAromaticRing = element !== this.element;\r\n this.bondCount = 0;\r\n this.chirality = '';\r\n this.isStereoCenter = false;\r\n this.priority = 0;\r\n this.mainChain = false;\r\n this.hydrogenDirection = 'down';\r\n this.subtreeDepth = 1;\r\n this.hasHydrogen = false;\r\n }\r\n\r\n /**\r\n * Adds a neighbouring element to this atom.\r\n * \r\n * @param {String} element A string representing an element.\r\n */\r\n addNeighbouringElement(element) {\r\n this.neighbouringElements.push(element);\r\n }\r\n\r\n /**\r\n * Attaches a pseudo element (e.g. Ac) to the atom.\r\n * @param {String} element The element identifier (e.g. Br, C, ...).\r\n * @param {String} previousElement The element that is part of the main chain (not the terminals that are converted to the pseudo element or concatinated).\r\n * @param {Number} [hydrogenCount=0] The number of hydrogens for the element.\r\n * @param {Number} [charge=0] The charge for the element.\r\n */\r\n attachPseudoElement(element, previousElement, hydrogenCount = 0, charge = 0) {\r\n if (hydrogenCount === null) {\r\n hydrogenCount = 0;\r\n }\r\n\r\n if (charge === null) {\r\n charge = 0;\r\n }\r\n\r\n let key = hydrogenCount + element + charge;\r\n\r\n if (this.attachedPseudoElements[key]) {\r\n this.attachedPseudoElements[key].count += 1;\r\n } else {\r\n this.attachedPseudoElements[key] = {\r\n element: element,\r\n count: 1,\r\n hydrogenCount: hydrogenCount,\r\n previousElement: previousElement,\r\n charge: charge\r\n };\r\n }\r\n\r\n this.hasAttachedPseudoElements = true;\r\n }\r\n\r\n /**\r\n * Returns the attached pseudo elements sorted by hydrogen count (ascending).\r\n *\r\n * @returns {Object} The sorted attached pseudo elements.\r\n */\r\n getAttachedPseudoElements() {\r\n let ordered = {};\r\n let that = this;\r\n\r\n Object.keys(this.attachedPseudoElements).sort().forEach(function (key) {\r\n ordered[key] = that.attachedPseudoElements[key];\r\n });\r\n\r\n return ordered;\r\n }\r\n\r\n /**\r\n * Returns the number of attached pseudo elements.\r\n *\r\n * @returns {Number} The number of attached pseudo elements.\r\n */\r\n getAttachedPseudoElementsCount() {\r\n return Object.keys(this.attachedPseudoElements).length;\r\n }\r\n\r\n /**\r\n * Returns whether this atom is a heteroatom (not C and not H).\r\n *\r\n * @returns {Boolean} A boolean indicating whether this atom is a heteroatom.\r\n */\r\n isHeteroAtom() {\r\n return this.element !== 'C' && this.element !== 'H';\r\n }\r\n\r\n /**\r\n * Defines this atom as the anchor for a ring. When doing repositionings of the vertices and the vertex associated with this atom is moved, the center of this ring is moved as well.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n addAnchoredRing(ringId) {\r\n if (!ArrayHelper.contains(this.anchoredRings, {\r\n value: ringId\r\n })) {\r\n this.anchoredRings.push(ringId);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of ringbonds (breaks in rings to generate the MST of the smiles) within this atom is connected to.\r\n *\r\n * @returns {Number} The number of ringbonds this atom is connected to.\r\n */\r\n getRingbondCount() {\r\n return this.ringbonds.length;\r\n }\r\n\r\n /**\r\n * Backs up the current rings.\r\n */\r\n backupRings() {\r\n this.originalRings = Array(this.rings.length);\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings[i] = this.rings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recent backed up rings.\r\n */\r\n restoreRings() {\r\n this.rings = Array(this.originalRings.length);\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings[i] = this.originalRings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not two atoms share a common ringbond id. A ringbond is a break in a ring created when generating the spanning tree of a structure.\r\n *\r\n * @param {Atom} atomA An atom.\r\n * @param {Atom} atomB An atom.\r\n * @returns {Boolean} A boolean indicating whether or not two atoms share a common ringbond.\r\n */\r\n haveCommonRingbond(atomA, atomB) {\r\n for (let i = 0; i < atomA.ringbonds.length; i++) {\r\n for (let j = 0; j < atomB.ringbonds.length; j++) {\r\n if (atomA.ringbonds[i].id == atomB.ringbonds[j].id) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not the neighbouring elements of this atom equal the supplied array.\r\n * \r\n * @param {String[]} arr An array containing all the elements that are neighbouring this atom. E.g. ['C', 'O', 'O', 'N']\r\n * @returns {Boolean} A boolean indicating whether or not the neighbours match the supplied array of elements.\r\n */\r\n neighbouringElementsEqual(arr) {\r\n if (arr.length !== this.neighbouringElements.length) {\r\n return false;\r\n }\r\n\r\n arr.sort();\r\n this.neighbouringElements.sort();\r\n\r\n for (var i = 0; i < this.neighbouringElements.length; i++) {\r\n if (arr[i] !== this.neighbouringElements[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the atomic number of this atom.\r\n * \r\n * @returns {Number} The atomic number of this atom.\r\n */\r\n getAtomicNumber() {\r\n return Atom.atomicNumbers[this.element];\r\n }\r\n\r\n /**\r\n * Get the maximum number of bonds for this atom.\r\n * \r\n * @returns {Number} The maximum number of bonds of this atom.\r\n */\r\n getMaxBonds() {\r\n return Atom.maxBonds[this.element];\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to their maximum bonds.\r\n */\r\n static get maxBonds() {\r\n return {\r\n 'H': 1,\r\n 'C': 4,\r\n 'N': 3,\r\n 'O': 2,\r\n 'P': 3,\r\n 'S': 2,\r\n 'B': 3,\r\n 'F': 1,\r\n 'I': 1,\r\n 'Cl': 1,\r\n 'Br': 1\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic number.\r\n */\r\n static get atomicNumbers() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic mass.\r\n */\r\n static get mass() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n}\r\n\r\nmodule.exports = Atom;","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Ring = require('./Ring');\r\nconst { getChargeText } = require('./UtilityFunctions');\r\n\r\n/** \r\n * A class wrapping a canvas element.\r\n * \r\n * @property {HTMLElement} canvas The HTML element for the canvas associated with this CanvasWrapper instance.\r\n * @property {CanvasRenderingContext2D} ctx The CanvasRenderingContext2D of the canvas associated with this CanvasWrapper instance.\r\n * @property {Object} colors The colors object as defined in the SmilesDrawer options.\r\n * @property {Object} opts The SmilesDrawer options.\r\n * @property {Number} drawingWidth The width of the canvas.\r\n * @property {Number} drawingHeight The height of the canvas.\r\n * @property {Number} realWidth The width of the canvas real.\r\n * @property {Number} realHeight The height of the canvas real.\r\n * @property {Number} offsetX The horizontal offset required for centering the drawing.\r\n * @property {Number} offsetY The vertical offset required for centering the drawing.\r\n * @property {Number} fontLarge The large font size in pt.\r\n * @property {Number} fontSmall The small font size in pt.\r\n */\r\nclass CanvasWrapper {\r\n /**\r\n * The constructor for the class CanvasWrapper.\r\n *\r\n * @param {(String|HTMLElement)} target The canvas id or the canvas HTMLElement.\r\n * @param {ThemeManager} themeManager Theme manager for setting proper colors.\r\n * @param {Object} options The smiles drawer options object.\r\n */\r\n constructor(target, themeManager, options) {\r\n if (typeof target === 'string' || target instanceof String) {\r\n this.canvas = document.getElementById(target);\r\n } else {\r\n this.canvas = target;\r\n }\r\n\r\n this.ctx = this.canvas.getContext('2d');\r\n this.themeManager = themeManager;\r\n this.opts = options;\r\n this.drawingWidth = 0.0;\r\n this.drawingHeight = 0.0;\r\n this.realWidth = 0.0;\r\n this.realHeight = 0.0;\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n this.fontLarge = this.opts.fontSizeLarge + 'pt Helvetica, Arial, sans-serif';\r\n this.fontSmall = this.opts.fontSizeSmall + 'pt Helvetica, Arial, sans-serif';\r\n\r\n this.updateSize(this.opts.width, this.opts.height);\r\n\r\n this.ctx.font = this.fontLarge;\r\n this.hydrogenWidth = this.ctx.measureText('H').width;\r\n this.halfHydrogenWidth = this.hydrogenWidth / 2.0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // TODO: Find out why clear was here.\r\n // this.clear();\r\n }\r\n\r\n /**\r\n * Update the width and height of the canvas\r\n * \r\n * @param {Number} width \r\n * @param {Number} height \r\n */\r\n updateSize(width, height) {\r\n this.devicePixelRatio = window.devicePixelRatio || 1;\r\n this.backingStoreRatio = this.ctx.webkitBackingStorePixelRatio || this.ctx.mozBackingStorePixelRatio ||\r\n this.ctx.msBackingStorePixelRatio || this.ctx.oBackingStorePixelRatio ||\r\n this.ctx.backingStorePixelRatio || 1;\r\n this.ratio = this.devicePixelRatio / this.backingStoreRatio;\r\n\r\n this.canvas.width = width * this.ratio;\r\n this.canvas.height = height * this.ratio;\r\n if (this.ratio !== 1) {\r\n this.realWidth = width;\r\n this.realHeight = height;\r\n this.canvas.style.width = width + 'px';\r\n this.canvas.style.height = height + 'px';\r\n this.ctx.setTransform(this.ratio, 0, 0, this.ratio, 0, 0);\r\n }\r\n }\r\n\r\n /**\r\n * Sets a provided theme.\r\n *\r\n * @param {Object} theme A theme from the smiles drawer options.\r\n */\r\n setTheme(theme) {\r\n this.colors = theme;\r\n }\r\n\r\n /**\r\n * Scale the canvas based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n scale(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n var padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n var scaleX = this.canvas.offsetWidth / this.drawingWidth;\r\n var scaleY = this.canvas.offsetHeight / this.drawingHeight;\r\n\r\n var scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n\r\n this.ctx.scale(scale, scale);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.canvas.offsetHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.canvas.offsetWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Resets the transform of the canvas.\r\n */\r\n reset() {\r\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.colors) {\r\n return this.colors[key];\r\n }\r\n\r\n return this.colors['C'];\r\n }\r\n\r\n /**\r\n * Draws a circle to a canvas context.\r\n * @param {Number} x The x coordinate of the circles center.\r\n * @param {Number} y The y coordinate of the circles center.\r\n * @param {Number} radius The radius of the circle\r\n * @param {String} color A hex encoded color.\r\n * @param {Boolean} [fill=true] Whether to fill or stroke the circle.\r\n * @param {Boolean} [debug=false] Draw in debug mode.\r\n * @param {String} [debugText=''] A debug message.\r\n */\r\n drawCircle(x, y, radius, color, fill = true, debug = false, debugText = '') {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.lineWidth = 1.5;\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, radius, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n\r\n if (debug) {\r\n if (fill) {\r\n ctx.fillStyle = '#f00';\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = '#f00';\r\n ctx.stroke();\r\n }\r\n\r\n this.drawDebugText(x, y, debugText);\r\n } else {\r\n if (fill) {\r\n ctx.fillStyle = color;\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = color;\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a line to a canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} [dashed=false] Whether or not the line is dashed.\r\n * @param {Number} [alpha=1.0] The alpha value of the color.\r\n */\r\n drawLine(line, dashed = false, alpha = 1.0) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(4.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n // Draw the \"shadow\"\r\n if (!dashed) {\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness + 1.2;\r\n ctx.strokeStyle = this.themeManager.getColor('BACKGROUND');\r\n ctx.stroke();\r\n ctx.globalCompositeOperation = 'source-over';\r\n ctx.restore();\r\n }\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n\r\n let gradient = this.ctx.createLinearGradient(l.x, l.y, r.x, r.y);\r\n if (line.isDecayPoint) {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(\"DECAY\"));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(\"DECAY\"));\r\n } else {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n }\r\n\r\n if (dashed) {\r\n ctx.setLineDash([1, 1.5]);\r\n ctx.lineWidth = this.opts.bondThickness / 1.5;\r\n }\r\n\r\n if (alpha < 1.0) {\r\n ctx.globalAlpha = alpha;\r\n }\r\n\r\n ctx.strokeStyle = gradient;\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Number} width The wedge width.\r\n */\r\n drawWedge(line, width = 1.0) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(5.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l;\r\n let end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness));\r\n let u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness));\r\n let v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness));\r\n let w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(t.x, t.y);\r\n ctx.lineTo(u.x, u.y);\r\n ctx.lineTo(v.x, v.y);\r\n ctx.lineTo(w.x, w.y);\r\n\r\n let gradient = this.ctx.createRadialGradient(r.x, r.y, this.opts.bondLength, r.x, r.y, 0);\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n let l = line.getLeftVector().clone();\r\n let r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start;\r\n let end;\r\n let sStart;\r\n let sEnd;\r\n\r\n let shortLine = line.clone();\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n\r\n shortLine.shortenRight(1.0);\r\n\r\n sStart = shortLine.getRightVector().clone();\r\n sEnd = shortLine.getLeftVector().clone();\r\n } else {\r\n start = l;\r\n end = r;\r\n\r\n shortLine.shortenLeft(1.0);\r\n\r\n sStart = shortLine.getLeftVector().clone();\r\n sEnd = shortLine.getRightVector().clone();\r\n }\r\n\r\n sStart.x += offsetX;\r\n sStart.y += offsetY;\r\n sEnd.x += offsetX;\r\n sEnd.y += offsetY;\r\n\r\n let dir = Vector2.subtract(end, start).normalize();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n let length = line.getLength();\r\n let step = 1.25 / (length / (this.opts.bondThickness * 3.0));\r\n\r\n let changed = false;\r\n for (var t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length);\r\n let startDash = Vector2.add(start, to);\r\n let width = 1.5 * t;\r\n let dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n if (!changed && t > 0.5) {\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.strokeStyle = this.themeManager.getColor(line.getRightElement()) || this.themeManager.getColor('C');\r\n changed = true;\r\n }\r\n \r\n startDash.subtract(dashOffset);\r\n ctx.moveTo(startDash.x, startDash.y);\r\n startDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n ctx.lineTo(startDash.x, startDash.y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.font = '5px Droid Sans, sans-serif';\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'top';\r\n ctx.fillStyle = '#ff0000';\r\n ctx.fillText(text, x + this.offsetX, y + this.offsetY);\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a ball to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, this.opts.bondLength / 4.5, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a point to the canvas.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, 1.5, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, 0.75, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'alphabetic';\r\n\r\n // Charge\r\n let chargeText = '';\r\n let chargeWidth = 0;\r\n\r\n if (charge) {\r\n chargeText = getChargeText(charge);\r\n\r\n ctx.font = this.fontSmall;\r\n chargeWidth = ctx.measureText(chargeText).width;\r\n }\r\n\r\n let isotopeText = '0';\r\n let isotopeWidth = 0;\r\n\r\n if (isotope > 0) {\r\n isotopeText = isotope.toString();\r\n ctx.font = this.fontSmall;\r\n isotopeWidth = ctx.measureText(isotopeText).width;\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') && \r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = { '0O': { element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: '' } };\r\n charge = 0;\r\n }\r\n\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillStyle = this.themeManager.getColor('BACKGROUND');\r\n\r\n let dim = ctx.measureText(elementName);\r\n\r\n dim.totalWidth = dim.width + chargeWidth;\r\n dim.height = parseInt(this.fontLarge, 10);\r\n\r\n let r = (dim.width > this.opts.fontSizeLarge) ? dim.width : this.opts.fontSizeLarge;\r\n r /= 1.5;\r\n\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, r, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n let cursorPos = -dim.width / 2.0;\r\n let cursorPosLeft = -dim.width / 2.0;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fillText(elementName, x + offsetX + cursorPos, y + this.opts.halfFontSizeLarge + offsetY);\r\n cursorPos += dim.width;\r\n\r\n if (charge) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(chargeText, x + offsetX + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += chargeWidth;\r\n }\r\n\r\n if (isotope > 0) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(isotopeText, x + offsetX + cursorPosLeft - isotopeWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPosLeft -= isotopeWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hydrogenWidth = 0;\r\n let hydrogenCountWidth = 0;\r\n\r\n if (hydrogens === 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n cursorPosLeft -= hydrogenWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.fillText('H', hx, hy);\r\n\r\n cursorPos += hydrogenWidth;\r\n } else if (hydrogens > 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n ctx.font = this.fontSmall;\r\n hydrogenCountWidth = ctx.measureText(hydrogens).width;\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillText('H', hx, hy);\r\n\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogens, hx + this.halfHydrogenWidth + hydrogenCountWidth, hy + this.opts.fifthFontSizeSmall);\r\n\r\n cursorPos += hydrogenWidth + this.halfHydrogenWidth + hydrogenCountWidth;\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let openParenthesisWidth = 0;\r\n let closeParenthesisWidth = 0;\r\n\r\n let element = attachedPseudoElement[key].element;\r\n let elementCount = attachedPseudoElement[key].count;\r\n let hydrogenCount = attachedPseudoElement[key].hydrogenCount;\r\n let elementCharge = attachedPseudoElement[key].charge;\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n openParenthesisWidth = ctx.measureText('(').width;\r\n closeParenthesisWidth = ctx.measureText(')').width;\r\n }\r\n\r\n let elementWidth = ctx.measureText(element).width;\r\n let elementCountWidth = 0;\r\n\r\n let elementChargeText = '';\r\n let elementChargeWidth = 0;\r\n\r\n hydrogenWidth = 0;\r\n\r\n if (hydrogenCount > 0) {\r\n hydrogenWidth = this.hydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n elementCountWidth = ctx.measureText(elementCount).width;\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n elementChargeText = getChargeText(elementCharge);\r\n elementChargeWidth = ctx.measureText(elementChargeText).width;\r\n }\r\n\r\n hydrogenCountWidth = 0;\r\n\r\n if (hydrogenCount > 1) {\r\n hydrogenCountWidth = ctx.measureText(hydrogenCount).width;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(element);\r\n\r\n if (elementCount > 0) {\r\n cursorPosLeft -= elementCountWidth;\r\n }\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= closeParenthesisWidth;\r\n ctx.fillText(')', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText('(', hx + cursorPos, hy);\r\n cursorPos += openParenthesisWidth;\r\n }\r\n }\r\n\r\n if (direction === 'left') {\r\n cursorPosLeft -= elementWidth;\r\n ctx.fillText(element, hx + cursorPosLeft, hy)\r\n } else {\r\n ctx.fillText(element, hx + cursorPos, hy);\r\n cursorPos += elementWidth;\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n ctx.fillText('H', hx + cursorPosLeft, hy);\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPosLeft + hydrogenWidth, hy + this.opts.fifthFontSizeSmall);\r\n }\r\n } else {\r\n ctx.fillText('H', hx + cursorPos, hy);\r\n cursorPos += hydrogenWidth;\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += hydrogenCountWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= openParenthesisWidth;\r\n ctx.fillText('(', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText(')', hx + cursorPos, hy);\r\n cursorPos += closeParenthesisWidth;\r\n }\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementCount, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, hy + this.opts.fifthFontSizeSmall);\r\n } else {\r\n ctx.fillText(elementCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += elementCountWidth;\r\n }\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementChargeText, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n } else {\r\n ctx.fillText(elementChargeText, hx + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += elementChargeWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\n getChargeText(charge) {\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Draws a dubug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n this.drawCircle(x, y, 2, color, true, true, debugText);\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Clear the canvas.\r\n *\r\n */\r\n clear() {\r\n this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = CanvasWrapper;","//@ts-check\r\n\r\nclass DecayPoint {\r\n\r\n /**\r\n * Enum values for Decay points\r\n * ALL use all variants of decay points\r\n * COO -CO-O- type of decay\r\n * CONH -CO-NH- type of decay\r\n * @return {{ALL: number, COO: number, CONH: number}}\r\n */\r\n static get VALUES() {\r\n return { ALL: 0, COO: 1, CONH: 2 };\r\n }\r\n}\r\n\r\nmodule.exports = DecayPoint;\r\n","//@ts-check\r\n\r\nclass DecayState {\r\n\r\n static get VALUES() {\r\n return { NO: 0, STANDARD: 1, SOURCE: 2, STANDARD_AND_SOURCE: 3};\r\n }\r\n}\r\n\r\nmodule.exports = DecayState;\r\n","\r\nclass Direction {\r\n\r\n static get VALUES() {\r\n return { N: 0, POLYKETIDE: 1, C: 2 };\r\n }\r\n\r\n static getProperValue(isPolyketide, vertexElement, vertexId, firstVertexId) {\r\n if (isPolyketide) {\r\n return this.VALUES.POLYKETIDE;\r\n }\r\n if (vertexElement === \"C\" && vertexId !== firstVertexId) {\r\n return this.VALUES.C;\r\n }\r\n return this.VALUES.N;\r\n }\r\n\r\n}\r\n\r\nmodule.exports= Direction;\r\n","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Atom = require('./Atom');\r\nconst Ring = require('./Ring');\r\nconst RingConnection = require('./RingConnection');\r\nconst CanvasWrapper = require('./CanvasWrapper');\r\nconst Graph = require('./Graph');\r\nconst SSSR = require('./SSSR');\r\nconst DecayState = require('./DecayState');\r\nconst ThemeManager = require('./ThemeManager');\r\n\r\n/**\r\n * The main class of the application representing the smiles drawer\r\n *\r\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\r\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\r\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} totalOverlapScore The current internal total overlap score.\r\n * @property {Object} defaultOptions The default options.\r\n * @property {Object} opts The merged options.\r\n * @property {Object} theme The current theme.\r\n */\r\nclass Drawer {\r\n /**\r\n * The constructor for the class SmilesDrawer.\r\n *\r\n * @param {Object} options An object containing custom values for different options. It is merged with the default options.\r\n */\r\n constructor(options) {\r\n this.graph = null;\r\n this.doubleBondConfigCount = 0;\r\n this.doubleBondConfig = null;\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n this.canvasWrapper = null;\r\n this.totalOverlapScore = 0;\r\n\r\n this.defaultOptions = {\r\n width: 500,\r\n height: 500,\r\n offsetX: 0, /* offsetX offset of canvas in page X. Typically canvas.offsetLeft */\r\n offsetY: 0, /* offsetY offset of canvas in page Y. Typically canvas.offsetTop */\r\n bondThickness: 0.6,\r\n bondLength: 15,\r\n shortBondLength: 0.85,\r\n bondSpacing: 0.18 * 15,\r\n atomVisualization: 'default',\r\n isomeric: true,\r\n debug: false,\r\n terminalCarbons: false,\r\n explicitHydrogens: false,\r\n overlapSensitivity: 0.42,\r\n overlapResolutionIterations: 1,\r\n compactDrawing: true,\r\n fontSizeLarge: 5,\r\n fontSizeSmall: 3,\r\n padding: 20.0,\r\n experimentalSSSR: false,\r\n kkThreshold: 0.1,\r\n kkInnerThreshold: 0.1,\r\n kkMaxIteration: 20000,\r\n kkMaxInnerIteration: 50,\r\n kkMaxEnergy: 1e9,\r\n drawDecayPoints: DecayState.VALUES.NO,\r\n decaySource: [],\r\n mouseTolerance: 3,\r\n themes: {\r\n dark: {\r\n C: '#fff',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#fff',\r\n BACKGROUND: '#141414',\r\n DECAY: '#027c21'\r\n },\r\n light: {\r\n C: '#222',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#222',\r\n BACKGROUND: '#fff',\r\n DECAY: '#027c21'\r\n }\r\n }\r\n };\r\n\r\n this.opts = this.extend(true, this.defaultOptions, options);\r\n this.opts.halfBondSpacing = this.opts.bondSpacing / 2.0;\r\n this.opts.bondLengthSq = this.opts.bondLength * this.opts.bondLength;\r\n this.opts.halfFontSizeLarge = this.opts.fontSizeLarge / 2.0;\r\n this.opts.quarterFontSizeLarge = this.opts.fontSizeLarge / 4.0;\r\n this.opts.fifthFontSizeSmall = this.opts.fontSizeSmall / 5.0;\r\n\r\n // Set the default theme.\r\n this.theme = this.opts.themes.dark;\r\n\r\n this.drawDecayPoints = this.opts.drawDecayPoints;\r\n }\r\n\r\n /**\r\n * A helper method to extend the default options with user supplied ones.\r\n */\r\n extend() {\r\n let that = this;\r\n let extended = {};\r\n let deep = false;\r\n let i = 0;\r\n let length = arguments.length;\r\n\r\n if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {\r\n deep = arguments[0];\r\n i++;\r\n }\r\n\r\n let merge = function (obj) {\r\n for (var prop in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, prop)) {\r\n if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\r\n extended[prop] = that.extend(true, extended[prop], obj[prop]);\r\n } else {\r\n extended[prop] = obj[prop];\r\n }\r\n }\r\n }\r\n };\r\n\r\n for (; i < length; i++) {\r\n let obj = arguments[i];\r\n merge(obj);\r\n }\r\n\r\n return extended;\r\n }\r\n\r\n /**\r\n * Is setup to draw decay points?\r\n * when boolean this.drawDecayPoint is true then return isDecay\r\n * @param isDecay bool - edge.isDecay\r\n * @returns {Boolean}\r\n */\r\n isDrawDecayPoint(isDecay) {\r\n return this.drawDecayPoints !== DecayState.VALUES.NO && isDecay;\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to a canvas element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n this.initDraw(data, themeName, infoOnly);\r\n\r\n if (!this.infoOnly) {\r\n this.themeManager = new ThemeManager(this.opts.themes, themeName);\r\n this.canvasWrapper = new CanvasWrapper(target, this.themeManager, this.opts);\r\n }\r\n\r\n if (!infoOnly) {\r\n this.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n\r\n if (this.opts.debug) {\r\n console.log(this.graph);\r\n console.log(this.rings);\r\n console.log(this.ringConnections);\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n if (this.canvasWrapper) {\r\n this.canvasWrapper.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of rings this edge is a part of.\r\n *\r\n * @param {Number} edgeId The id of an edge.\r\n * @returns {Number} The number of rings the provided edge is part of.\r\n */\r\n edgeRingCount(edgeId) {\r\n let edge = this.graph.edges[edgeId];\r\n let a = this.graph.vertices[edge.sourceId];\r\n let b = this.graph.vertices[edge.targetId];\r\n\r\n return Math.min(a.value.rings.length, b.value.rings.length);\r\n }\r\n\r\n /**\r\n * Returns an array containing the bridged rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all bridged rings associated with this molecule.\r\n */\r\n getBridgedRings() {\r\n let bridgedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n bridgedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return bridgedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all fused rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all fused rings associated with this molecule.\r\n */\r\n getFusedRings() {\r\n let fusedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isFused) {\r\n fusedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return fusedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all spiros associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all spiros associated with this molecule.\r\n */\r\n getSpiros() {\r\n let spiros = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isSpiro) {\r\n spiros.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return spiros;\r\n }\r\n\r\n /**\r\n * Returns a string containing a semicolon and new-line separated list of ring properties: Id; Members Count; Neighbours Count; IsSpiro; IsFused; IsBridged; Ring Count (subrings of bridged rings)\r\n *\r\n * @returns {String} A string as described in the method description.\r\n */\r\n printRingInfo() {\r\n let result = '';\r\n for (let i = 0; i < this.rings.length; i++) {\r\n const ring = this.rings[i];\r\n\r\n result += ring.id + ';';\r\n result += ring.members.length + ';';\r\n result += ring.neighbours.length + ';';\r\n result += ring.isSpiro ? 'true;' : 'false;';\r\n result += ring.isFused ? 'true;' : 'false;';\r\n result += ring.isBridged ? 'true;' : 'false;';\r\n result += ring.rings.length + ';';\r\n result += '\\n';\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Rotates the drawing to make the widest dimension horizontal.\r\n */\r\n rotateDrawing() {\r\n // Rotate the vertices to make the molecule align horizontally\r\n // Find the longest distance\r\n let a = 0;\r\n let b = 0;\r\n let maxDist = 0;\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertexA = this.graph.vertices[i];\r\n\r\n if (!vertexA.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n for (let j = i + 1; j < this.graph.vertices.length; j++) {\r\n let vertexB = this.graph.vertices[j];\r\n\r\n if (!vertexB.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = vertexA.position.distanceSq(vertexB.position);\r\n\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n a = i;\r\n b = j;\r\n }\r\n }\r\n }\r\n\r\n let angle = -Vector2.subtract(this.graph.vertices[a].position, this.graph.vertices[b].position).angle();\r\n\r\n if (!isNaN(angle)) {\r\n // Round to 30 degrees\r\n let remainder = angle % 0.523599;\r\n\r\n // Round either up or down in 30 degree steps\r\n if (remainder < 0.2617995) {\r\n angle = angle - remainder;\r\n } else {\r\n angle += 0.523599 - remainder;\r\n }\r\n\r\n // Finally, rotate everything\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (i === b) {\r\n continue;\r\n }\r\n\r\n this.graph.vertices[i].position.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.rings[i].center.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.totalOverlapScore;\r\n }\r\n\r\n /**\r\n * Returns the ring count of the current molecule.\r\n *\r\n * @returns {Number} The ring count.\r\n */\r\n getRingCount() {\r\n return this.rings.length;\r\n }\r\n\r\n /**\r\n * Checks whether or not the current molecule a bridged ring.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not the current molecule a bridged ring.\r\n */\r\n hasBridgedRing() {\r\n return this.bridgedRing;\r\n }\r\n\r\n /**\r\n * Returns the number of heavy atoms (non-hydrogen) in the current molecule.\r\n *\r\n * @returns {Number} The heavy atom count.\r\n */\r\n getHeavyAtomCount() {\r\n let hac = 0;\r\n\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.element !== 'H') {\r\n hac++;\r\n }\r\n }\r\n\r\n return hac;\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n let molecularFormula = '';\r\n let counts = new Map();\r\n\r\n // Initialize element count\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n let atom = this.graph.vertices[i].value;\r\n\r\n if (counts.has(atom.element)) {\r\n counts.set(atom.element, counts.get(atom.element) + 1);\r\n } else {\r\n counts.set(atom.element, 1);\r\n }\r\n\r\n // Hydrogens attached to a chiral center were added as vertices,\r\n // those in non chiral brackets are added here\r\n if (atom.bracket && !atom.bracket.chirality) {\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + atom.bracket.hcount);\r\n } else {\r\n counts.set('H', atom.bracket.hcount);\r\n }\r\n }\r\n\r\n // Add the implicit hydrogens according to valency, exclude\r\n // bracket atoms as they were handled and always have the number\r\n // of hydrogens specified explicitly\r\n if (!atom.bracket) {\r\n let nHydrogens = Atom.maxBonds[atom.element] - atom.bondCount;\r\n\r\n if (atom.isPartOfAromaticRing) {\r\n nHydrogens--;\r\n }\r\n\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + nHydrogens);\r\n } else {\r\n counts.set('H', nHydrogens);\r\n }\r\n }\r\n }\r\n\r\n if (counts.has('C')) {\r\n let count = counts.get('C');\r\n molecularFormula += 'C' + (count > 1 ? count : '');\r\n counts.delete('C');\r\n }\r\n\r\n if (counts.has('H')) {\r\n let count = counts.get('H');\r\n molecularFormula += 'H' + (count > 1 ? count : '');\r\n counts.delete('H');\r\n }\r\n\r\n let elements = Object.keys(Atom.atomicNumbers).sort();\r\n\r\n elements.map(e => {\r\n if (counts.has(e)) {\r\n let count = counts.get(e);\r\n molecularFormula += e + (count > 1 ? count : '');\r\n }\r\n });\r\n\r\n return molecularFormula;\r\n }\r\n\r\n /**\r\n * Returns the type of the ringbond (e.g. '=' for a double bond). The ringbond represents the break in a ring introduced when creating the MST. If the two vertices supplied as arguments are not part of a common ringbond, the method returns null.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(String|null)} Returns the ringbond type or null, if the two supplied vertices are not connected by a ringbond.\r\n */\r\n getRingbondType(vertexA, vertexB) {\r\n // Checks whether the two vertices are the ones connecting the ring\r\n // and what the bond type should be.\r\n if (vertexA.value.getRingbondCount() < 1 || vertexB.value.getRingbondCount() < 1) {\r\n return null;\r\n }\r\n\r\n for (var i = 0; i < vertexA.value.ringbonds.length; i++) {\r\n for (var j = 0; j < vertexB.value.ringbonds.length; j++) {\r\n // if(i != j) continue;\r\n if (vertexA.value.ringbonds[i].id === vertexB.value.ringbonds[j].id) {\r\n // If the bonds are equal, it doesn't matter which bond is returned.\r\n // if they are not equal, return the one that is not the default (\"-\")\r\n if (vertexA.value.ringbonds[i].bondType === '-') {\r\n return vertexB.value.ringbonds[j].bond;\r\n } else {\r\n return vertexA.value.ringbonds[i].bond;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n initDraw(data, themeName, infoOnly) {\r\n this.data = data;\r\n this.infoOnly = infoOnly;\r\n\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n\r\n this.graph = new Graph(data, this.opts.isomeric, this.opts);\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n this.bridgedRing = false;\r\n\r\n // Reset those, in case the previous drawn SMILES had a dangling \\ or /\r\n this.doubleBondConfigCount = null;\r\n this.doubleBondConfig = null;\r\n\r\n this.initRings();\r\n this.initHydrogens();\r\n this.graph.findDecayPoints();\r\n }\r\n\r\n processGraph() {\r\n this.position();\r\n\r\n // Restore the ring information (removes bridged rings and replaces them with the original, multiple, rings)\r\n this.restoreRingInformation();\r\n\r\n // Atoms bonded to the same ring atom\r\n this.resolvePrimaryOverlaps();\r\n\r\n let overlapScore = this.getOverlapScore();\r\n\r\n this.totalOverlapScore = this.getOverlapScore().total;\r\n\r\n for (var o = 0; o < this.opts.overlapResolutionIterations; o++) {\r\n for (var i = 0; i < this.graph.edges.length; i++) {\r\n let edge = this.graph.edges[i];\r\n if (this.isEdgeRotatable(edge)) {\r\n let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\r\n let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\r\n\r\n // Only rotate the shorter subtree\r\n let a = edge.targetId;\r\n let b = edge.sourceId;\r\n\r\n if (subTreeDepthA > subTreeDepthB) {\r\n a = edge.sourceId;\r\n b = edge.targetId;\r\n }\r\n\r\n let subTreeOverlap = this.getSubtreeOverlapScore(b, a, overlapScore.vertexScores);\r\n if (subTreeOverlap.value > this.opts.overlapSensitivity) {\r\n let vertexA = this.graph.vertices[a];\r\n let vertexB = this.graph.vertices[b];\r\n let neighboursB = vertexB.getNeighbours(a);\r\n\r\n if (neighboursB.length === 1) {\r\n let neighbour = this.graph.vertices[neighboursB[0]];\r\n let angle = neighbour.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbour.id, vertexB.id, angle, vertexB.position);\r\n // If the new overlap is bigger, undo change\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbour.id, vertexB.id, -angle, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n } else if (neighboursB.length === 2) {\r\n // Switch places / sides\r\n // If vertex a is in a ring, do nothing\r\n if (vertexB.value.rings.length !== 0 && vertexA.value.rings.length !== 0) {\r\n continue;\r\n }\r\n\r\n let neighbourA = this.graph.vertices[neighboursB[0]];\r\n let neighbourB = this.graph.vertices[neighboursB[1]];\r\n\r\n if (neighbourA.value.rings.length === 1 && neighbourB.value.rings.length === 1) {\r\n // Both neighbours in same ring. TODO: does this create problems with wedges? (up = down and vice versa?)\r\n if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\r\n continue;\r\n }\r\n // TODO: Rotate circle\r\n } else if (neighbourA.value.rings.length !== 0 || neighbourB.value.rings.length !== 0) {\r\n continue;\r\n } else {\r\n let angleA = neighbourA.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n let angleB = neighbourB.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbourA.id, vertexB.id, angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, angleB, vertexB.position);\r\n\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbourA.id, vertexB.id, -angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, -angleB, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n }\r\n }\r\n\r\n overlapScore = this.getOverlapScore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.resolveSecondaryOverlaps(overlapScore.scores);\r\n\r\n if (this.opts.isomeric) {\r\n this.annotateStereochemistry();\r\n }\r\n\r\n // Initialize pseudo elements or shortcuts\r\n if (this.opts.compactDrawing && this.opts.atomVisualization === 'default') {\r\n this.initPseudoElements();\r\n }\r\n\r\n this.rotateDrawing();\r\n }\r\n\r\n /**\r\n * Initializes rings and ringbonds for the current molecule.\r\n */\r\n initRings() {\r\n let openBonds = new Map();\r\n\r\n // Close the open ring bonds (spanning tree -> graph)\r\n for (let i = this.graph.vertices.length - 1; i >= 0; i--) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.ringbonds.length === 0) {\r\n continue;\r\n }\r\n\r\n for (let j = 0; j < vertex.value.ringbonds.length; j++) {\r\n let ringbondId = vertex.value.ringbonds[j].id;\r\n let ringbondBond = vertex.value.ringbonds[j].bond;\r\n\r\n // If the other ringbond id has not been discovered,\r\n // add it to the open bonds map and continue.\r\n // if the other ringbond id has already been discovered,\r\n // create a bond between the two atoms.\r\n if (!openBonds.has(ringbondId)) {\r\n openBonds.set(ringbondId, [vertex.id, ringbondBond]);\r\n } else {\r\n let sourceVertexId = vertex.id;\r\n let targetVertexId = openBonds.get(ringbondId)[0];\r\n let targetRingbondBond = openBonds.get(ringbondId)[1];\r\n let edge = new Edge(sourceVertexId, targetVertexId, 1);\r\n edge.setBondType(targetRingbondBond || ringbondBond || '-');\r\n let edgeId = this.graph.addEdge(edge);\r\n let targetVertex = this.graph.vertices[targetVertexId];\r\n\r\n vertex.addRingbondChild(targetVertexId, j);\r\n vertex.value.addNeighbouringElement(targetVertex.value.element);\r\n targetVertex.addRingbondChild(sourceVertexId, j);\r\n targetVertex.value.addNeighbouringElement(vertex.value.element);\r\n vertex.edges.push(edgeId);\r\n targetVertex.edges.push(edgeId);\r\n\r\n openBonds.delete(ringbondId);\r\n }\r\n }\r\n }\r\n\r\n // Get the rings in the graph (the SSSR)\r\n let rings = SSSR.getRings(this.graph, this.opts.experimentalSSSR);\r\n\r\n if (rings === null) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < rings.length; i++) {\r\n let ringVertices = [...rings[i]];\r\n let ringId = this.addRing(new Ring(ringVertices));\r\n\r\n // Add the ring to the atoms\r\n for (let j = 0; j < ringVertices.length; j++) {\r\n this.graph.vertices[ringVertices[j]].value.rings.push(ringId);\r\n }\r\n }\r\n\r\n // Find connection between rings\r\n // Check for common vertices and create ring connections. This is a bit\r\n // ugly, but the ringcount is always fairly low (< 100)\r\n for (let i = 0; i < this.rings.length - 1; i++) {\r\n for (let j = i + 1; j < this.rings.length; j++) {\r\n let a = this.rings[i];\r\n let b = this.rings[j];\r\n let ringConnection = new RingConnection(a, b);\r\n\r\n // If there are no vertices in the ring connection, then there\r\n // is no ring connection\r\n if (ringConnection.vertices.size > 0) {\r\n this.addRingConnection(ringConnection);\r\n }\r\n }\r\n }\r\n\r\n // Add neighbours to the rings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n ring.neighbours = RingConnection.getNeighbours(this.ringConnections, ring.id);\r\n }\r\n\r\n // Anchor the ring to one of it's members, so that the ring center will always\r\n // be tied to a single vertex when doing repositionings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n this.graph.vertices[ring.members[0]].value.addAnchoredRing(ring.id);\r\n }\r\n\r\n // Backup the ring information to restore after placing the bridged ring.\r\n // This is needed in order to identify aromatic rings and stuff like this in\r\n // rings that are member of the superring.\r\n this.backupRingInformation();\r\n\r\n\r\n // Replace rings contained by a larger bridged ring with a bridged ring\r\n while (this.rings.length > 0) {\r\n let id = -1;\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isPartOfBridgedRing(ring.id) && !ring.isBridged) {\r\n id = ring.id;\r\n }\r\n }\r\n\r\n if (id === -1) {\r\n break;\r\n }\r\n\r\n let ring = this.getRing(id);\r\n\r\n let involvedRings = this.getBridgedRingRings(ring.id);\r\n\r\n this.bridgedRing = true;\r\n this.createBridgedRing(involvedRings, ring.members[0]);\r\n\r\n // Remove the rings\r\n for (let i = 0; i < involvedRings.length; i++) {\r\n this.removeRing(involvedRings[i]);\r\n }\r\n }\r\n }\r\n\r\n initHydrogens() {\r\n // Do not draw hydrogens except when they are connected to a stereocenter connected to two or more rings.\r\n if (!this.opts.explicitHydrogens) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.element !== 'H') {\r\n continue;\r\n }\r\n\r\n // Hydrogens should have only one neighbour, so just take the first\r\n // Also set hasHydrogen true on connected atom\r\n let neighbour = this.graph.vertices[vertex.neighbours[0]];\r\n neighbour.value.hasHydrogen = true;\r\n\r\n if (!neighbour.value.isStereoCenter || neighbour.value.rings.length < 2 && !neighbour.value.bridgedRing ||\r\n neighbour.value.bridgedRing && neighbour.value.originalRings.length < 2) {\r\n vertex.value.isDrawn = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns all rings connected by bridged bonds starting from the ring with the supplied ring id.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array containing all ring ids of rings part of a bridged ring system.\r\n */\r\n getBridgedRingRings(ringId) {\r\n let involvedRings = Array();\r\n let that = this;\r\n\r\n let recurse = function (r) {\r\n let ring = that.getRing(r);\r\n\r\n involvedRings.push(r);\r\n\r\n for (let i = 0; i < ring.neighbours.length; i++) {\r\n let n = ring.neighbours[i];\r\n\r\n if (involvedRings.indexOf(n) === -1 &&\r\n n !== r &&\r\n RingConnection.isBridge(that.ringConnections, that.graph.vertices, r, n)) {\r\n recurse(n);\r\n }\r\n }\r\n };\r\n\r\n recurse(ringId);\r\n\r\n return ArrayHelper.unique(involvedRings);\r\n }\r\n\r\n /**\r\n * Checks whether or not a ring is part of a bridged ring.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not the supplied ring (by id) is part of a bridged ring system.\r\n */\r\n isPartOfBridgedRing(ringId) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].containsRing(ringId) &&\r\n this.ringConnections[i].isBridge(this.graph.vertices)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Creates a bridged ring.\r\n *\r\n * @param {Number[]} ringIds An array of ids of rings involved in the bridged ring.\r\n * @param {Number} sourceVertexId The vertex id to start the bridged ring discovery from.\r\n * @returns {Ring} The bridged ring.\r\n */\r\n createBridgedRing(ringIds, sourceVertexId) {\r\n let ringMembers = new Set();\r\n let vertices = new Set();\r\n let neighbours = new Set();\r\n\r\n for (let i = 0; i < ringIds.length; i++) {\r\n let ring = this.getRing(ringIds[i]);\r\n ring.isPartOfBridged = true;\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n vertices.add(ring.members[j]);\r\n }\r\n\r\n for (let j = 0; j < ring.neighbours.length; j++) {\r\n let id = ring.neighbours[j];\r\n\r\n if (ringIds.indexOf(id) === -1) {\r\n neighbours.add(ring.neighbours[j]);\r\n }\r\n }\r\n }\r\n\r\n // A vertex is part of the bridged ring if it only belongs to\r\n // one of the rings (or to another ring\r\n // which is not part of the bridged ring).\r\n let leftovers = new Set();\r\n\r\n for (let id of vertices) {\r\n let vertex = this.graph.vertices[id];\r\n let intersection = ArrayHelper.intersection(ringIds, vertex.value.rings);\r\n\r\n if (vertex.value.rings.length === 1 || intersection.length === 1) {\r\n ringMembers.add(vertex.id);\r\n } else {\r\n leftovers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Vertices can also be part of multiple rings and lay on the bridged ring,\r\n // however, they have to have at least two neighbours that are not part of\r\n // two rings\r\n let insideRing = Array();\r\n for (let id of leftovers) {\r\n let vertex = this.graph.vertices[id];\r\n let onRing = false;\r\n\r\n for (let j = 0; j < vertex.edges.length; j++) {\r\n if (this.edgeRingCount(vertex.edges[j]) === 1) {\r\n onRing = true;\r\n }\r\n }\r\n\r\n if (onRing) {\r\n vertex.value.isBridgeNode = true;\r\n ringMembers.add(vertex.id);\r\n } else {\r\n vertex.value.isBridge = true;\r\n ringMembers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Create the ring\r\n let ring = new Ring([...ringMembers]);\r\n this.addRing(ring);\r\n\r\n ring.isBridged = true;\r\n ring.neighbours = [...neighbours];\r\n for (let i = 0; i < ringIds.length; i++) {\r\n ring.rings.push(this.getRing(ringIds[i]).clone());\r\n }\r\n\r\n for (let i = 0; i < ring.members.length; i++) {\r\n this.graph.vertices[ring.members[i]].value.bridgedRing = ring.id;\r\n }\r\n\r\n // Atoms inside the ring are no longer part of a ring but are now\r\n // associated with the bridged ring\r\n for (let i = 0; i < insideRing.length; i++) {\r\n let vertex = this.graph.vertices[insideRing[i]];\r\n vertex.value.rings = Array();\r\n }\r\n\r\n // Remove former rings from members of the bridged ring and add the bridged ring\r\n for (let id of ringMembers) {\r\n let vertex = this.graph.vertices[id];\r\n vertex.value.rings = ArrayHelper.removeAll(vertex.value.rings, ringIds);\r\n vertex.value.rings.push(ring.id);\r\n }\r\n\r\n // Remove all the ring connections no longer used\r\n for (let i = 0; i < ringIds.length; i++) {\r\n for (let j = i + 1; j < ringIds.length; j++) {\r\n this.removeRingConnectionsBetween(ringIds[i], ringIds[j]);\r\n }\r\n }\r\n\r\n // Update the ring connections and add this ring to the neighbours neighbours\r\n for (let id of neighbours) {\r\n let connections = this.getRingConnections(id, ringIds);\r\n\r\n for (let j = 0; j < connections.length; j++) {\r\n this.getRingConnection(connections[j]).updateOther(ring.id, id);\r\n }\r\n\r\n this.getRing(id).neighbours.push(ring.id);\r\n }\r\n\r\n return ring;\r\n }\r\n\r\n /**\r\n * Checks whether or not two vertices are in the same ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices are in the same ring.\r\n */\r\n areVerticesInSameRing(vertexA, vertexB) {\r\n // This is a little bit lighter (without the array and push) than\r\n // getCommonRings().length > 0\r\n for (let i = 0; i < vertexA.value.rings.length; i++) {\r\n for (let j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] === vertexB.value.rings[j]) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array of ring ids shared by both vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Number[]} An array of ids of rings shared by the two vertices.\r\n */\r\n getCommonRings(vertexA, vertexB) {\r\n let commonRings = Array();\r\n\r\n for (var i = 0; i < vertexA.value.rings.length; i++) {\r\n for (var j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] == vertexB.value.rings[j]) {\r\n commonRings.push(vertexA.value.rings[i]);\r\n }\r\n }\r\n }\r\n\r\n return commonRings;\r\n }\r\n\r\n /**\r\n * Returns the aromatic or largest ring shared by the two vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(Ring|null)} If an aromatic common ring exists, that ring, else the largest (non-aromatic) ring, else null.\r\n */\r\n getLargestOrAromaticCommonRing(vertexA, vertexB) {\r\n let commonRings = this.getCommonRings(vertexA, vertexB);\r\n let maxSize = 0;\r\n let largestCommonRing = null;\r\n\r\n for (let i = 0; i < commonRings.length; i++) {\r\n let ring = this.getRing(commonRings[i]);\r\n let size = ring.getSize();\r\n\r\n if (ring.isBenzeneLike(this.graph.vertices)) {\r\n return ring;\r\n } else if (size > maxSize) {\r\n maxSize = size;\r\n largestCommonRing = ring;\r\n }\r\n }\r\n\r\n return largestCommonRing;\r\n }\r\n\r\n /**\r\n * Returns an array of vertices positioned at a specified location.\r\n *\r\n * @param {Vector2} position The position to search for vertices.\r\n * @param {Number} radius The radius within to search.\r\n * @param {Number} excludeVertexId A vertex id to be excluded from the search results.\r\n * @returns {Number[]} An array containing vertex ids in a given location.\r\n */\r\n getVerticesAt(position, radius, excludeVertexId) {\r\n let locals = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.id === excludeVertexId || !vertex.positioned) {\r\n continue;\r\n }\r\n\r\n let distance = position.distanceSq(vertex.position);\r\n\r\n if (distance <= radius * radius) {\r\n locals.push(vertex.id);\r\n }\r\n }\r\n\r\n return locals;\r\n }\r\n\r\n /**\r\n * Returns the closest vertex (connected as well as unconnected).\r\n *\r\n * @param {Vertex} vertex The vertex of which to find the closest other vertex.\r\n * @returns {Vertex} The closest vertex.\r\n */\r\n getClosestVertex(vertex) {\r\n let minDist = 99999;\r\n let minVertex = null;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i];\r\n\r\n if (v.id === vertex.id) {\r\n continue;\r\n }\r\n\r\n let distSq = vertex.position.distanceSq(v.position);\r\n\r\n if (distSq < minDist) {\r\n minDist = distSq;\r\n minVertex = v;\r\n }\r\n }\r\n\r\n return minVertex;\r\n }\r\n\r\n /**\r\n * Add a ring to this representation of a molecule.\r\n *\r\n * @param {Ring} ring A new ring.\r\n * @returns {Number} The ring id of the new ring.\r\n */\r\n addRing(ring) {\r\n ring.id = this.ringIdCounter++;\r\n this.rings.push(ring);\r\n\r\n return ring.id;\r\n }\r\n\r\n /**\r\n * Removes a ring from the array of rings associated with the current molecule.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n removeRing(ringId) {\r\n this.rings = this.rings.filter(function (item) {\r\n return item.id !== ringId;\r\n });\r\n\r\n // Also remove ring connections involving this ring\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.firstRingId !== ringId && item.secondRingId !== ringId;\r\n });\r\n\r\n // Remove the ring as neighbour of other rings\r\n for (var i = 0; i < this.rings.length; i++) {\r\n let r = this.rings[i];\r\n r.neighbours = r.neighbours.filter(function (item) {\r\n return item !== ringId;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets a ring object from the array of rings associated with the current molecule by its id. The ring id is not equal to the index, since rings can be added and removed when processing bridged rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Ring} A ring associated with the current molecule.\r\n */\r\n getRing(ringId) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].id == ringId) {\r\n return this.rings[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Add a ring connection to this representation of a molecule.\r\n *\r\n * @param {RingConnection} ringConnection A new ringConnection.\r\n * @returns {Number} The ring connection id of the new ring connection.\r\n */\r\n addRingConnection(ringConnection) {\r\n ringConnection.id = this.ringConnectionIdCounter++;\r\n this.ringConnections.push(ringConnection);\r\n\r\n return ringConnection.id;\r\n }\r\n\r\n /**\r\n * Removes a ring connection from the array of rings connections associated with the current molecule.\r\n *\r\n * @param {Number} ringConnectionId A ring connection id.\r\n */\r\n removeRingConnection(ringConnectionId) {\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.id !== ringConnectionId;\r\n });\r\n }\r\n\r\n /**\r\n * Removes all ring connections between two vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n */\r\n removeRingConnectionsBetween(vertexIdA, vertexIdB) {\r\n let toRemove = Array();\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let ringConnection = this.ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === vertexIdA && ringConnection.secondRingId === vertexIdB ||\r\n ringConnection.firstRingId === vertexIdB && ringConnection.secondRingId === vertexIdA) {\r\n toRemove.push(ringConnection.id);\r\n }\r\n }\r\n\r\n for (let i = 0; i < toRemove.length; i++) {\r\n this.removeRingConnection(toRemove[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Get a ring connection with a given id.\r\n *\r\n * @param {Number} id\r\n * @returns {RingConnection} The ring connection with the specified id.\r\n */\r\n getRingConnection(id) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].id == id) {\r\n return this.ringConnections[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the ring connections between a ring and a set of rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @param {Number[]} ringIds An array of ring ids.\r\n * @returns {Number[]} An array of ring connection ids.\r\n */\r\n getRingConnections(ringId, ringIds) {\r\n let ringConnections = Array();\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let rc = this.ringConnections[i];\r\n\r\n for (let j = 0; j < ringIds.length; j++) {\r\n let id = ringIds[j];\r\n\r\n if (rc.firstRingId === ringId && rc.secondRingId === id ||\r\n rc.firstRingId === id && rc.secondRingId === ringId) {\r\n ringConnections.push(rc.id);\r\n }\r\n }\r\n }\r\n\r\n return ringConnections;\r\n }\r\n\r\n /**\r\n * Returns the overlap score of the current molecule based on its positioned vertices. The higher the score, the more overlaps occur in the structure drawing.\r\n *\r\n * @returns {Object} Returns the total overlap score and the overlap score of each vertex sorted by score (higher to lower). Example: { total: 99, scores: [ { id: 0, score: 22 }, ... ] }\r\n */\r\n getOverlapScore() {\r\n let total = 0.0;\r\n let overlapScores = new Float32Array(this.graph.vertices.length);\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n overlapScores[i] = 0;\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let j = this.graph.vertices.length;\r\n while (--j > i) {\r\n let a = this.graph.vertices[i];\r\n let b = this.graph.vertices[j];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = Vector2.subtract(a.position, b.position).lengthSq();\r\n\r\n if (dist < this.opts.bondLengthSq) {\r\n let weighted = (this.opts.bondLength - Math.sqrt(dist)) / this.opts.bondLength;\r\n total += weighted;\r\n overlapScores[i] += weighted;\r\n overlapScores[j] += weighted;\r\n }\r\n }\r\n }\r\n\r\n let sortable = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n sortable.push({\r\n id: i,\r\n score: overlapScores[i]\r\n });\r\n }\r\n\r\n sortable.sort(function (a, b) {\r\n return b.score - a.score;\r\n });\r\n\r\n return {\r\n total: total,\r\n scores: sortable,\r\n vertexScores: overlapScores\r\n };\r\n }\r\n\r\n /**\r\n * When drawing a double bond, choose the side to place the double bond. E.g. a double bond should always been drawn inside a ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @param {Vector2[]} sides An array containing the two normals of the line spanned by the two provided vertices.\r\n * @returns {Object} Returns an object containing the following information: {\r\n totalSideCount: Counts the sides of each vertex in the molecule, is an array [ a, b ],\r\n totalPosition: Same as position, but based on entire molecule,\r\n sideCount: Counts the sides of each neighbour, is an array [ a, b ],\r\n position: which side to position the second bond, is 0 or 1, represents the index in the normal array. This is based on only the neighbours\r\n anCount: the number of neighbours of vertexA,\r\n bnCount: the number of neighbours of vertexB\r\n }\r\n */\r\n chooseSide(vertexA, vertexB, sides) {\r\n // Check which side has more vertices\r\n // Get all the vertices connected to the both ends\r\n let an = vertexA.getNeighbours(vertexB.id);\r\n let bn = vertexB.getNeighbours(vertexA.id);\r\n let anCount = an.length;\r\n let bnCount = bn.length;\r\n\r\n // All vertices connected to the edge vertexA to vertexB\r\n let tn = ArrayHelper.merge(an, bn);\r\n\r\n // Only considering the connected vertices\r\n let sideCount = [0, 0];\r\n\r\n for (let i = 0; i < tn.length; i++) {\r\n let v = this.graph.vertices[tn[i]].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n sideCount[0]++;\r\n } else {\r\n sideCount[1]++;\r\n }\r\n }\r\n\r\n // Considering all vertices in the graph, this is to resolve ties\r\n // from the above side counts\r\n let totalSideCount = [0, 0];\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n totalSideCount[0]++;\r\n } else {\r\n totalSideCount[1]++;\r\n }\r\n }\r\n\r\n return {\r\n totalSideCount: totalSideCount,\r\n totalPosition: totalSideCount[0] > totalSideCount[1] ? 0 : 1,\r\n sideCount: sideCount,\r\n position: sideCount[0] > sideCount[1] ? 0 : 1,\r\n anCount: anCount,\r\n bnCount: bnCount\r\n };\r\n }\r\n\r\n /**\r\n * Sets the center for a ring.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n setRingCenter(ring) {\r\n let ringSize = ring.getSize();\r\n let total = new Vector2(0, 0);\r\n\r\n for (let i = 0; i < ringSize; i++) {\r\n total.add(this.graph.vertices[ring.members[i]].position);\r\n }\r\n\r\n ring.center = total.divide(ringSize);\r\n }\r\n\r\n /**\r\n * Gets the center of a ring contained within a bridged ring and containing a given vertex.\r\n *\r\n * @param {Ring} ring A bridged ring.\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {Vector2} The center of the subring that containing the vertex.\r\n */\r\n getSubringCenter(ring, vertex) {\r\n let rings = vertex.value.originalRings;\r\n let center = ring.center;\r\n let smallest = Number.MAX_VALUE;\r\n\r\n // Always get the smallest ring.\r\n for (let i = 0; i < rings.length; i++) {\r\n for (let j = 0; j < ring.rings.length; j++) {\r\n if (rings[i] === ring.rings[j].id) {\r\n if (ring.rings[j].getSize() < smallest) {\r\n center = ring.rings[j].center;\r\n smallest = ring.rings[j].getSize();\r\n }\r\n }\r\n }\r\n }\r\n\r\n return center;\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let that = this;\r\n let drawn = Array(this.graph.edges.length);\r\n drawn.fill(false);\r\n\r\n this.graph.traverseBF(0, function (vertex) {\r\n let edges = that.graph.getEdges(vertex.id);\r\n for (let i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n that.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isRingAromatic(ring)) {\r\n this.canvasWrapper.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bonds to the canvas.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let that = this;\r\n let edge = this.graph.edges[edgeId];\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n let elementA = vertexA.value.element;\r\n let elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && this.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position;\r\n let b = vertexB.position;\r\n let normals = this.getEdgeNormals(edge);\r\n\r\n // Create a point on each side of the line\r\n let sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || this.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && this.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = this.areVerticesInSameRing(vertexA, vertexB);\r\n let s = this.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = this.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n }\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n this.canvasWrapper.drawLine(line, true);\r\n } else {\r\n this.canvasWrapper.drawLine(line);\r\n }\r\n\r\n // The normal edge\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.center || vertexA.isTerminal() && vertexB.isTerminal()) {\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1) {\r\n // Both lines are the same length here\r\n // Add the spacing to the edges (which are of unit length)\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.sideCount[0] > s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.sideCount[0] < s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] > s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] <= s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n this.canvasWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.wedge === 'down') {\r\n this.canvasWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else {\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n this.canvasWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(this.graph.vertices);\r\n let isTerminal = this.opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (this.opts.atomVisualization === 'allballs') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || this.graph.vertices.length === 1) {\r\n if (this.opts.atomVisualization === 'default') {\r\n this.canvasWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (this.opts.atomVisualization === 'balls') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = this.graph.vertices[vertex.neighbours[0]].position;\r\n let b = this.graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n this.canvasWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n // this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (this.opts.debug) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let center = this.rings[i].center;\r\n this.canvasWrapper.drawDebugPoint(center.x, center.y, 'r: ' + this.rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Position the vertices according to their bonds and properties.\r\n */\r\n position() {\r\n let startVertex = null;\r\n\r\n // Always start drawing at a bridged ring if there is one\r\n // If not, start with a ring\r\n // else, start with 0\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.bridgedRing !== null) {\r\n startVertex = this.graph.vertices[i];\r\n break;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n startVertex = this.graph.vertices[this.rings[i].members[0]];\r\n }\r\n }\r\n\r\n if (this.rings.length > 0 && startVertex === null) {\r\n startVertex = this.graph.vertices[this.rings[0].members[0]];\r\n }\r\n\r\n if (startVertex === null) {\r\n startVertex = this.graph.vertices[0];\r\n }\r\n\r\n this.createNextBond(startVertex, null, 0.0);\r\n }\r\n\r\n /**\r\n * Stores the current information associated with rings.\r\n */\r\n backupRingInformation() {\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings.push(this.rings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n this.originalRingConnections.push(this.ringConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.backupRings();\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recently backed up information associated with rings.\r\n */\r\n restoreRingInformation() {\r\n // Get the subring centers from the bridged rings\r\n let bridgedRings = this.getBridgedRings();\r\n\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n for (let i = 0; i < bridgedRings.length; i++) {\r\n let bridgedRing = bridgedRings[i];\r\n\r\n for (var j = 0; j < bridgedRing.rings.length; j++) {\r\n let ring = bridgedRing.rings[j];\r\n this.originalRings[ring.id].center = ring.center;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings.push(this.originalRings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.originalRingConnections.length; i++) {\r\n this.ringConnections.push(this.originalRingConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.restoreRings();\r\n }\r\n }\r\n\r\n // TODO: This needs some cleaning up\r\n\r\n /**\r\n * Creates a new ring, that is, positiones all the vertices inside a ring.\r\n *\r\n * @param {Ring} ring The ring to position.\r\n * @param {(Vector2|null)} [center=null] The center of the ring to be created.\r\n * @param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.\r\n * @param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.\r\n * @param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.\r\n */\r\n createRing(ring, center = null, startVertex = null, previousVertex = null) {\r\n if (ring.positioned) {\r\n return;\r\n }\r\n\r\n center = center ? center : new Vector2(0, 0);\r\n\r\n let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);\r\n let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let angle = MathHelper.centralAngle(ring.getSize());\r\n\r\n ring.centralAngle = angle;\r\n\r\n let a = startingAngle;\r\n let that = this;\r\n let startVertexId = (startVertex) ? startVertex.id : null;\r\n\r\n if (ring.members.indexOf(startVertexId) === -1) {\r\n if (startVertex) {\r\n startVertex.positioned = false;\r\n }\r\n\r\n startVertexId = ring.members[0];\r\n }\r\n\r\n // If the ring is bridged, then draw the vertices inside the ring\r\n // using a force based approach\r\n if (ring.isBridged) {\r\n this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength,\r\n this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration,\r\n this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);\r\n ring.positioned = true;\r\n\r\n // Update the center of the bridged ring\r\n this.setRingCenter(ring);\r\n center = ring.center;\r\n\r\n // Setting the centers for the subrings\r\n for (let i = 0; i < ring.rings.length; i++) {\r\n this.setRingCenter(ring.rings[i]);\r\n }\r\n } else {\r\n ring.eachMember(this.graph.vertices, function (v) {\r\n let vertex = that.graph.vertices[v];\r\n\r\n if (!vertex.positioned) {\r\n vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);\r\n }\r\n\r\n a += angle;\r\n\r\n if (!ring.isBridged || ring.rings.length < 3) {\r\n vertex.angle = a;\r\n vertex.positioned = true;\r\n }\r\n }, startVertexId, (previousVertex) ? previousVertex.id : null);\r\n }\r\n\r\n ring.positioned = true;\r\n ring.center = center;\r\n\r\n // Draw neighbours in decreasing order of connectivity\r\n for (let i = 0; i < orderedNeighbours.length; i++) {\r\n let neighbour = this.getRing(orderedNeighbours[i].neighbour);\r\n\r\n if (neighbour.positioned) {\r\n continue;\r\n }\r\n\r\n let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);\r\n\r\n if (vertices.length === 2) {\r\n // This ring is a fused ring\r\n ring.isFused = true;\r\n neighbour.isFused = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n let vertexB = this.graph.vertices[vertices[1]];\r\n\r\n // Get middle between vertex A and B\r\n let midpoint = Vector2.midpoint(vertexA.position, vertexB.position);\r\n\r\n // Get the normals to the line between A and B\r\n let normals = Vector2.normals(vertexA.position, vertexB.position);\r\n\r\n // Normalize the normals\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n // Set length from middle of side to center (the apothem)\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n let apothem = MathHelper.apothem(r, neighbour.getSize());\r\n\r\n normals[0].multiplyScalar(apothem).add(midpoint);\r\n normals[1].multiplyScalar(apothem).add(midpoint);\r\n\r\n // Pick the normal which results in a larger distance to the previous center\r\n // Also check whether it's inside another ring\r\n let nextCenter = normals[0];\r\n if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {\r\n nextCenter = normals[1];\r\n }\r\n\r\n // Get the vertex (A or B) which is in clock-wise direction of the other\r\n let posA = Vector2.subtract(vertexA.position, nextCenter);\r\n let posB = Vector2.subtract(vertexB.position, nextCenter);\r\n\r\n if (posA.clockwise(posB) === -1) {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA, vertexB);\r\n }\r\n } else {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexB, vertexA);\r\n }\r\n }\r\n } else if (vertices.length === 1) {\r\n // This ring is a spiro\r\n ring.isSpiro = true;\r\n neighbour.isSpiro = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n\r\n // Get the vector pointing from the shared vertex to the new centpositioner\r\n let nextCenter = Vector2.subtract(center, vertexA.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n // Get the distance from the vertex to the center\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertexA.position);\r\n\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA);\r\n }\r\n }\r\n }\r\n\r\n // Next, draw atoms that are not part of a ring that are directly attached to this ring\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let ringMember = this.graph.vertices[ring.members[i]];\r\n let ringMemberNeighbours = ringMember.neighbours;\r\n\r\n // If there are multiple, the ovlerap will be resolved in the appropriate step\r\n for (let j = 0; j < ringMemberNeighbours.length; j++) {\r\n let v = this.graph.vertices[ringMemberNeighbours[j]];\r\n\r\n if (v.positioned) {\r\n continue;\r\n }\r\n\r\n v.value.isConnectedToRing = true;\r\n this.createNextBond(v, ringMember, 0.0);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Rotate an entire subtree by an angle around a center.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree that is to rotate.\r\n * @param {Number} angle An angle in randians.\r\n * @param {Vector2} center The rotational center.\r\n */\r\n rotateSubtree(vertexId, parentVertexId, angle, center) {\r\n let that = this;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n vertex.position.rotateAround(angle, center);\r\n\r\n for (var i = 0; i < vertex.value.anchoredRings.length; i++) {\r\n let ring = that.rings[vertex.value.anchoredRings[i]];\r\n\r\n if (ring) {\r\n ring.center.rotateAround(angle, center);\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Gets the overlap score of a subtree.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree.\r\n * @param {Number[]} vertexOverlapScores An array containing the vertex overlap scores indexed by vertex id.\r\n * @returns {Object} An object containing the total overlap score and the center of mass of the subtree weighted by overlap score { value: 0.2, center: new Vector2() }.\r\n */\r\n getSubtreeOverlapScore(vertexId, parentVertexId, vertexOverlapScores) {\r\n let that = this;\r\n let score = 0;\r\n let center = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n if (!vertex.value.isDrawn) {\r\n return;\r\n }\r\n\r\n let s = vertexOverlapScores[vertex.id];\r\n if (s > that.opts.overlapSensitivity) {\r\n score += s;\r\n count++;\r\n }\r\n\r\n let position = that.graph.vertices[vertex.id].position.clone();\r\n position.multiplyScalar(s);\r\n center.add(position);\r\n });\r\n\r\n center.divide(score);\r\n\r\n return {\r\n value: score / count,\r\n center: center\r\n };\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass.\r\n *\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMass() {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass in the neighbourhood of a given position.\r\n *\r\n * @param {Vector2} vec The point at which to look for neighbours.\r\n * @param {Number} [r=currentBondLength*2.0] The radius of vertices to include.\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMassInNeigbourhood(vec, r = this.opts.bondLength * 2.0) {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n let rSq = r * r;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned && vec.distanceSq(vertex.position) < rSq) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Resolve primary (exact) overlaps, such as two vertices that are connected to the same ring vertex.\r\n */\r\n resolvePrimaryOverlaps() {\r\n let overlaps = Array();\r\n let done = Array(this.graph.vertices.length);\r\n\r\n // Looking for overlaps created by two bonds coming out of a ring atom, which both point straight\r\n // away from the ring and are thus perfectly overlapping.\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n let vertex = this.graph.vertices[ring.members[j]];\r\n\r\n if (done[vertex.id]) {\r\n continue;\r\n }\r\n\r\n done[vertex.id] = true;\r\n\r\n let nonRingNeighbours = this.getNonRingNeighbours(vertex.id);\r\n\r\n if (nonRingNeighbours.length > 1) {\r\n // Look for rings where there are atoms with two bonds outside the ring (overlaps)\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n } else if (nonRingNeighbours.length === 1 && vertex.value.rings.length === 2) {\r\n // Look for bonds coming out of joined rings to adjust the angle, an example is: C1=CC(=CC=C1)[C@]12SCCN1CC1=CC=CC=C21\r\n // where the angle has to be adjusted to account for fused ring\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (let i = 0; i < overlaps.length; i++) {\r\n let overlap = overlaps[i];\r\n\r\n if (overlap.vertices.length === 2) {\r\n let a = overlap.vertices[0];\r\n let b = overlap.vertices[1];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let angle = (2 * Math.PI - this.getRing(overlap.rings[0]).getAngle()) / 6.0;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -angle, overlap.common.position);\r\n\r\n // Decide which way to rotate the vertices depending on the effect it has on the overlap score\r\n let overlapScore = this.getOverlapScore();\r\n let subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n let subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n let total = subTreeOverlapA.value + subTreeOverlapB.value;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n\r\n overlapScore = this.getOverlapScore();\r\n subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n\r\n if (subTreeOverlapA.value + subTreeOverlapB.value > total) {\r\n this.rotateSubtree(a.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n }\r\n } else if (overlap.vertices.length === 1) {\r\n if (overlap.rings.length === 2) {\r\n // TODO: Implement for more overlap resolution\r\n // console.log(overlap);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resolve secondary overlaps. Those overlaps are due to the structure turning back on itself.\r\n *\r\n * @param {Object[]} scores An array of objects sorted descending by score.\r\n * @param {Number} scores[].id A vertex id.\r\n * @param {Number} scores[].score The overlap score associated with the vertex id.\r\n */\r\n resolveSecondaryOverlaps(scores) {\r\n for (let i = 0; i < scores.length; i++) {\r\n if (scores[i].score > this.opts.overlapSensitivity) {\r\n let vertex = this.graph.vertices[scores[i].id];\r\n\r\n if (vertex.isTerminal()) {\r\n let closest = this.getClosestVertex(vertex);\r\n\r\n if (closest) {\r\n // If one of the vertices is the first one, the previous vertex is not the central vertex but the dummy\r\n // so take the next rather than the previous, which is vertex 1\r\n let closestPosition = null;\r\n\r\n if (closest.isTerminal()) {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.previousPosition\r\n } else {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.position\r\n }\r\n\r\n let vertexPreviousPosition = vertex.id === 0 ? this.graph.vertices[1].position : vertex.previousPosition;\r\n\r\n vertex.position.rotateAwayFrom(closestPosition, vertexPreviousPosition, MathHelper.toRad(20));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the last non-null or 0 angle vertex.\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex} The last vertex with an angle that was not 0 or null.\r\n */\r\n getLastVertexWithAngle(vertexId) {\r\n let angle = 0;\r\n let vertex = null;\r\n\r\n while (!angle && vertexId) {\r\n vertex = this.graph.vertices[vertexId];\r\n angle = vertex.angle;\r\n vertexId = vertex.parentVertexId;\r\n }\r\n\r\n return vertex;\r\n }\r\n\r\n /**\r\n * Positiones the next vertex thus creating a bond.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @param {Vertex} [previousVertex=null] The previous vertex which has been positioned.\r\n * @param {Number} [angle=0.0] The (global) angle of the vertex.\r\n * @param {Boolean} [originShortest=false] Whether the origin is the shortest subtree in the branch.\r\n * @param {Boolean} [skipPositioning=false] Whether or not to skip positioning and just check the neighbours.\r\n */\r\n createNextBond(vertex, previousVertex = null, angle = 0.0, originShortest = false, skipPositioning = false) {\r\n if (vertex.positioned && !skipPositioning) {\r\n return;\r\n }\r\n\r\n // If the double bond config was set on this vertex, do not check later\r\n let doubleBondConfigSet = false;\r\n\r\n // Keeping track of configurations around double bonds\r\n if (previousVertex) {\r\n let edge = this.graph.getEdge(vertex.id, previousVertex.id);\r\n\r\n if ((edge.bondType === '/' || edge.bondType === '\\\\') && ++this.doubleBondConfigCount % 2 === 1) {\r\n if (this.doubleBondConfig === null) {\r\n this.doubleBondConfig = edge.bondType;\r\n doubleBondConfigSet = true;\r\n\r\n // Switch if the bond is a branch bond and previous vertex is the first\r\n // TODO: Why is it different with the first vertex?\r\n if (previousVertex.parentVertexId === null && vertex.value.branchBond) {\r\n if (this.doubleBondConfig === '/') {\r\n this.doubleBondConfig = '\\\\';\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n this.doubleBondConfig = '/';\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If the current node is the member of one ring, then point straight away\r\n // from the center of the ring. However, if the current node is a member of\r\n // two rings, point away from the middle of the centers of the two rings\r\n if (!skipPositioning) {\r\n if (!previousVertex) {\r\n // Add a (dummy) previous position if there is no previous vertex defined\r\n // Since the first vertex is at (0, 0), create a vector at (bondLength, 0)\r\n // and rotate it by 90°\r\n\r\n let dummy = new Vector2(this.opts.bondLength, 0);\r\n dummy.rotate(MathHelper.toRad(-60));\r\n\r\n vertex.previousPosition = dummy;\r\n vertex.setPosition(this.opts.bondLength, 0);\r\n vertex.angle = MathHelper.toRad(-60);\r\n\r\n // Do not position the vertex if it belongs to a bridged ring that is positioned using a layout algorithm.\r\n if (vertex.value.bridgedRing === null) {\r\n vertex.positioned = true;\r\n }\r\n } else if (previousVertex.value.rings.length > 0) {\r\n let neighbours = previousVertex.neighbours;\r\n let joinedVertex = null;\r\n let pos = new Vector2(0.0, 0.0);\r\n\r\n if (previousVertex.value.bridgedRing === null && previousVertex.value.rings.length > 1) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n if (ArrayHelper.containsAll(neighbour.value.rings, previousVertex.value.rings)) {\r\n joinedVertex = neighbour;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (joinedVertex === null) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let v = this.graph.vertices[neighbours[i]];\r\n\r\n if (v.positioned && this.areVerticesInSameRing(v, previousVertex)) {\r\n pos.add(Vector2.subtract(v.position, previousVertex.position));\r\n }\r\n }\r\n\r\n pos.invert().normalize().multiplyScalar(this.opts.bondLength).add(previousVertex.position);\r\n } else {\r\n pos = joinedVertex.position.clone().rotateAround(Math.PI, previousVertex.position);\r\n }\r\n\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.setPositionFromVector(pos);\r\n vertex.positioned = true;\r\n } else {\r\n // If the previous vertex was not part of a ring, draw a bond based\r\n // on the global angle of the previous bond\r\n let v = new Vector2(this.opts.bondLength, 0);\r\n\r\n v.rotate(angle);\r\n v.add(previousVertex.position);\r\n\r\n vertex.setPositionFromVector(v);\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.positioned = true;\r\n }\r\n }\r\n\r\n // Go to next vertex\r\n // If two rings are connected by a bond ...\r\n if (vertex.value.bridgedRing !== null) {\r\n let nextRing = this.getRing(vertex.value.bridgedRing);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.members.length);\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else if (vertex.value.rings.length > 0) {\r\n let nextRing = this.getRing(vertex.value.rings[0]);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else {\r\n // Draw the non-ring vertices connected to this one\r\n let isStereoCenter = vertex.value.isStereoCenter;\r\n let tmpNeighbours = vertex.getNeighbours();\r\n let neighbours = Array();\r\n\r\n // Remove neighbours that are not drawn\r\n for (let i = 0; i < tmpNeighbours.length; i++) {\r\n if (this.graph.vertices[tmpNeighbours[i]].value.isDrawn) {\r\n neighbours.push(tmpNeighbours[i]);\r\n }\r\n }\r\n\r\n // Remove the previous vertex (which has already been drawn)\r\n if (previousVertex) {\r\n neighbours = ArrayHelper.remove(neighbours, previousVertex.id);\r\n }\r\n\r\n let previousAngle = vertex.getAngle();\r\n\r\n if (neighbours.length === 1) {\r\n let nextVertex = this.graph.vertices[neighbours[0]];\r\n\r\n // Make a single chain always cis except when there's a tribble (yes, this is a Star Trek reference) bond\r\n // or if there are successive double bonds. Added a ring check because if there is an aromatic ring the ring bond inside the ring counts as a double bond and leads to =-= being straight.\r\n if ((vertex.value.bondType === '#' || (previousVertex && previousVertex.value.bondType === '#')) ||\r\n vertex.value.bondType === '=' && previousVertex && previousVertex.value.rings.length === 0 &&\r\n previousVertex.value.bondType === '=' && vertex.value.branchBond !== '-') {\r\n vertex.value.drawExplicit = false;\r\n\r\n if (previousVertex) {\r\n let straightEdge1 = this.graph.getEdge(vertex.id, previousVertex.id);\r\n straightEdge1.center = true;\r\n }\r\n\r\n let straightEdge2 = this.graph.getEdge(vertex.id, nextVertex.id);\r\n straightEdge2.center = true;\r\n\r\n if (vertex.value.bondType === '#' || previousVertex && previousVertex.value.bondType === '#') {\r\n nextVertex.angle = 0.0;\r\n }\r\n\r\n nextVertex.drawExplicit = true;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else if (previousVertex && previousVertex.value.rings.length > 0) {\r\n // If coming out of a ring, always draw away from the center of mass\r\n let proposedAngleA = MathHelper.toRad(60);\r\n let proposedAngleB = -proposedAngleA;\r\n\r\n let proposedVectorA = new Vector2(this.opts.bondLength, 0);\r\n let proposedVectorB = new Vector2(this.opts.bondLength, 0);\r\n\r\n proposedVectorA.rotate(proposedAngleA).add(vertex.position);\r\n proposedVectorB.rotate(proposedAngleB).add(vertex.position);\r\n\r\n // let centerOfMass = this.getCurrentCenterOfMassInNeigbourhood(vertex.position, 100);\r\n let centerOfMass = this.getCurrentCenterOfMass();\r\n let distanceA = proposedVectorA.distanceSq(centerOfMass);\r\n let distanceB = proposedVectorB.distanceSq(centerOfMass);\r\n\r\n nextVertex.angle = distanceA < distanceB ? proposedAngleB : proposedAngleA;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else {\r\n let a = vertex.angle;\r\n // Take the min and max if the previous angle was in a 4-neighbourhood (90° angles)\r\n // TODO: If a is null or zero, it should be checked whether or not this one should go cis or trans, that is,\r\n // it should go into the oposite direction of the last non-null or 0 previous vertex / angle.\r\n if (previousVertex && previousVertex.neighbours.length > 3) {\r\n if (a > 0) {\r\n a = Math.min(1.0472, a);\r\n } else if (a < 0) {\r\n a = Math.max(-1.0472, a);\r\n } else {\r\n a = 1.0472;\r\n }\r\n } else if (!a) {\r\n let v = this.getLastVertexWithAngle(vertex.id);\r\n a = v.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n }\r\n\r\n // Handle configuration around double bonds\r\n if (previousVertex && !doubleBondConfigSet) {\r\n let bondType = this.graph.getEdge(vertex.id, nextVertex.id).bondType;\r\n\r\n if (bondType === '/') {\r\n if (this.doubleBondConfig === '/') {\r\n // Nothing to do since it will be trans per default\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n a = -a;\r\n }\r\n this.doubleBondConfig = null;\r\n } else if (bondType === '\\\\') {\r\n if (this.doubleBondConfig === '/') {\r\n a = -a;\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n // Nothing to do since it will be trans per default\r\n }\r\n this.doubleBondConfig = null;\r\n }\r\n }\r\n\r\n if (originShortest) {\r\n nextVertex.angle = a;\r\n } else {\r\n nextVertex.angle = -a;\r\n }\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n }\r\n } else if (neighbours.length === 2) {\r\n // If the previous vertex comes out of a ring, it doesn't have an angle set\r\n let a = vertex.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n\r\n // Check for the longer subtree - always go with cis for the longer subtree\r\n let subTreeDepthA = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let subTreeDepthB = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n\r\n let l = this.graph.vertices[neighbours[0]];\r\n let r = this.graph.vertices[neighbours[1]];\r\n\r\n l.value.subtreeDepth = subTreeDepthA;\r\n r.value.subtreeDepth = subTreeDepthB;\r\n\r\n // Also get the subtree for the previous direction (this is important when\r\n // the previous vertex is the shortest path)\r\n let subTreeDepthC = this.graph.getTreeDepth(previousVertex ? previousVertex.id : null, vertex.id);\r\n if (previousVertex) {\r\n previousVertex.value.subtreeDepth = subTreeDepthC;\r\n }\r\n\r\n let cis = 0;\r\n let trans = 1;\r\n\r\n // Carbons go always cis\r\n if (r.value.element === 'C' && l.value.element !== 'C' && subTreeDepthB > 1 && subTreeDepthA < 5) {\r\n cis = 1;\r\n trans = 0;\r\n } else if (r.value.element !== 'C' && l.value.element === 'C' && subTreeDepthA > 1 && subTreeDepthB < 5) {\r\n cis = 0;\r\n trans = 1;\r\n } else if (subTreeDepthB > subTreeDepthA) {\r\n cis = 1;\r\n trans = 0;\r\n }\r\n\r\n let cisVertex = this.graph.vertices[neighbours[cis]];\r\n let transVertex = this.graph.vertices[neighbours[trans]];\r\n\r\n // If the origin tree is the shortest, make them the main chain\r\n let originShortest = false;\r\n if (subTreeDepthC < subTreeDepthA && subTreeDepthC < subTreeDepthB) {\r\n originShortest = true;\r\n }\r\n\r\n transVertex.angle = a;\r\n cisVertex.angle = -a;\r\n\r\n if (this.doubleBondConfig === '\\\\') {\r\n if (transVertex.value.branchBond === '\\\\') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n } else if (this.doubleBondConfig === '/') {\r\n if (transVertex.value.branchBond === '/') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n }\r\n\r\n this.createNextBond(transVertex, vertex, previousAngle + transVertex.angle, originShortest);\r\n this.createNextBond(cisVertex, vertex, previousAngle + cisVertex.angle, originShortest);\r\n } else if (neighbours.length === 3) {\r\n // The vertex with the longest sub-tree should always go straight\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n\r\n let s = this.graph.vertices[neighbours[0]];\r\n let l = this.graph.vertices[neighbours[1]];\r\n let r = this.graph.vertices[neighbours[2]];\r\n\r\n s.value.subtreeDepth = d1;\r\n l.value.subtreeDepth = d2;\r\n r.value.subtreeDepth = d3;\r\n\r\n if (d2 > d1 && d2 > d3) {\r\n s = this.graph.vertices[neighbours[1]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[2]];\r\n } else if (d3 > d1 && d3 > d2) {\r\n s = this.graph.vertices[neighbours[2]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[1]];\r\n }\r\n\r\n // Create a cross if more than one subtree is of length > 1\r\n // or the vertex is connected to a ring\r\n if (previousVertex &&\r\n previousVertex.value.rings.length < 1 &&\r\n s.value.rings.length < 1 &&\r\n l.value.rings.length < 1 &&\r\n r.value.rings.length < 1 &&\r\n this.graph.getTreeDepth(l.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(r.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(s.id, vertex.id) > 1) {\r\n\r\n s.angle = -vertex.angle;\r\n if (vertex.angle >= 0) {\r\n l.angle = MathHelper.toRad(30);\r\n r.angle = MathHelper.toRad(90);\r\n } else {\r\n l.angle = -MathHelper.toRad(30);\r\n r.angle = -MathHelper.toRad(90);\r\n }\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n } else {\r\n s.angle = 0.0;\r\n l.angle = MathHelper.toRad(90);\r\n r.angle = -MathHelper.toRad(90);\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n }\r\n } else if (neighbours.length === 4) {\r\n // The vertex with the longest sub-tree should always go to the reflected opposide direction\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n let d4 = this.graph.getTreeDepth(neighbours[3], vertex.id);\r\n\r\n let w = this.graph.vertices[neighbours[0]];\r\n let x = this.graph.vertices[neighbours[1]];\r\n let y = this.graph.vertices[neighbours[2]];\r\n let z = this.graph.vertices[neighbours[3]];\r\n\r\n w.value.subtreeDepth = d1;\r\n x.value.subtreeDepth = d2;\r\n y.value.subtreeDepth = d3;\r\n z.value.subtreeDepth = d4;\r\n\r\n if (d2 > d1 && d2 > d3 && d2 > d4) {\r\n w = this.graph.vertices[neighbours[1]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[2]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d3 > d1 && d3 > d2 && d3 > d4) {\r\n w = this.graph.vertices[neighbours[2]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d4 > d1 && d4 > d2 && d4 > d3) {\r\n w = this.graph.vertices[neighbours[3]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[2]];\r\n }\r\n\r\n w.angle = -MathHelper.toRad(36);\r\n x.angle = MathHelper.toRad(36);\r\n y.angle = -MathHelper.toRad(108);\r\n z.angle = MathHelper.toRad(108);\r\n\r\n this.createNextBond(w, vertex, previousAngle + w.angle);\r\n this.createNextBond(x, vertex, previousAngle + x.angle);\r\n this.createNextBond(y, vertex, previousAngle + y.angle);\r\n this.createNextBond(z, vertex, previousAngle + z.angle);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Gets the vetex sharing the edge that is the common bond of two rings.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {(Number|null)} The id of a vertex sharing the edge that is the common bond of two rings with the vertex provided or null, if none.\r\n */\r\n getCommonRingbondNeighbour(vertex) {\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n\r\n if (ArrayHelper.containsAll(neighbour.value.rings, vertex.value.rings)) {\r\n return neighbour;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Check if a vector is inside any ring.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Boolean} A boolean indicating whether or not the point (vector) is inside any of the rings associated with the current molecule.\r\n */\r\n isPointInRing(vec) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (!ring.positioned) {\r\n continue;\r\n }\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let radiusSq = radius * radius;\r\n\r\n if (vec.distanceSq(ring.center) < radiusSq) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is part of a ring.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is part of a ring.\r\n */\r\n isEdgeInRing(edge) {\r\n let source = this.graph.vertices[edge.sourceId];\r\n let target = this.graph.vertices[edge.targetId];\r\n\r\n return this.areVerticesInSameRing(source, target);\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is rotatable.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is rotatable.\r\n */\r\n isEdgeRotatable(edge) {\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n\r\n // Only single bonds are rotatable\r\n if (edge.bondType !== '-') {\r\n return false;\r\n }\r\n\r\n // Do not rotate edges that have a further single bond to each side - do that!\r\n // If the bond is terminal, it doesn't make sense to rotate it\r\n // if (vertexA.getNeighbourCount() + vertexB.getNeighbourCount() < 5) {\r\n // return false;\r\n // }\r\n\r\n if (vertexA.isTerminal() || vertexB.isTerminal()) {\r\n return false;\r\n }\r\n\r\n // Ringbonds are not rotatable\r\n return !(vertexA.value.rings.length > 0 && vertexB.value.rings.length > 0 && this.areVerticesInSameRing(vertexA, vertexB));\r\n }\r\n\r\n /**\r\n * Check whether or not a ring is an implicitly defined aromatic ring (lower case smiles).\r\n *\r\n * @param {Ring} ring A ring.\r\n * @returns {Boolean} A boolean indicating whether or not a ring is implicitly defined as aromatic.\r\n */\r\n isRingAromatic(ring) {\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let vertex = this.graph.vertices[ring.members[i]];\r\n\r\n if (!vertex.value.isPartOfAromaticRing) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the normals of an edge.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Vector2[]} An array containing two vectors, representing the normals.\r\n */\r\n getEdgeNormals(edge) {\r\n let v1 = this.graph.vertices[edge.sourceId].position;\r\n let v2 = this.graph.vertices[edge.targetId].position;\r\n\r\n // Get the normalized normals for the edge\r\n return Vector2.units(v1, v2);\r\n }\r\n\r\n /**\r\n * Returns an array of vertices that are neighbouring a vertix but are not members of a ring (including bridges).\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex[]} An array of vertices.\r\n */\r\n getNonRingNeighbours(vertexId) {\r\n let nrneighbours = Array();\r\n let vertex = this.graph.vertices[vertexId];\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n let nIntersections = ArrayHelper.intersection(vertex.value.rings, neighbour.value.rings).length;\r\n\r\n if (nIntersections === 0 && neighbour.value.isBridge == false) {\r\n nrneighbours.push(neighbour);\r\n }\r\n }\r\n\r\n return nrneighbours;\r\n }\r\n\r\n /**\r\n * Annotaed stereochemistry information for visualization.\r\n */\r\n annotateStereochemistry() {\r\n let maxDepth = 10;\r\n\r\n // For each stereo-center\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (!vertex.value.isStereoCenter) {\r\n continue;\r\n }\r\n\r\n let neighbours = vertex.getNeighbours();\r\n let nNeighbours = neighbours.length;\r\n let priorities = Array(nNeighbours);\r\n\r\n for (let j = 0; j < nNeighbours; j++) {\r\n let visited = new Uint8Array(this.graph.vertices.length);\r\n let priority = Array(Array());\r\n visited[vertex.id] = 1;\r\n\r\n this.visitStereochemistry(neighbours[j], vertex.id, visited, priority, maxDepth, 0);\r\n\r\n // Sort each level according to atomic number\r\n for (let k = 0; k < priority.length; k++) {\r\n priority[k].sort(function (a, b) {\r\n return b - a\r\n });\r\n }\r\n\r\n priorities[j] = [j, priority];\r\n }\r\n\r\n let maxLevels = 0;\r\n let maxEntries = 0;\r\n for (let j = 0; j < priorities.length; j++) {\r\n if (priorities[j][1].length > maxLevels) {\r\n maxLevels = priorities[j][1].length;\r\n }\r\n\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n if (priorities[j][1][k].length > maxEntries) {\r\n maxEntries = priorities[j][1][k].length;\r\n }\r\n }\r\n }\r\n\r\n for (let j = 0; j < priorities.length; j++) {\r\n let diff = maxLevels - priorities[j][1].length;\r\n for (let k = 0; k < diff; k++) {\r\n priorities[j][1].push([]);\r\n }\r\n\r\n // Break ties by the position in the SMILES string as per specification\r\n priorities[j][1].push([neighbours[j]]);\r\n\r\n // Make all same length. Fill with zeroes.\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n let diff = maxEntries - priorities[j][1][k].length;\r\n\r\n for (let l = 0; l < diff; l++) {\r\n priorities[j][1][k].push(0);\r\n }\r\n }\r\n }\r\n\r\n priorities.sort(function (a, b) {\r\n for (let j = 0; j < a[1].length; j++) {\r\n for (let k = 0; k < a[1][j].length; k++) {\r\n if (a[1][j][k] > b[1][j][k]) {\r\n return -1;\r\n } else if (a[1][j][k] < b[1][j][k]) {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n\r\n let order = new Uint8Array(nNeighbours);\r\n for (let j = 0; j < nNeighbours; j++) {\r\n order[j] = priorities[j][0];\r\n vertex.value.priority = j;\r\n }\r\n\r\n // Check the angles between elements 0 and 1, and 0 and 2 to determine whether they are\r\n // drawn cw or ccw\r\n // TODO: OC(Cl)=[C@]=C(C)F currently fails here, however this is, IMHO, not a valid SMILES.\r\n let posA = this.graph.vertices[neighbours[order[0]]].position;\r\n let posB = this.graph.vertices[neighbours[order[1]]].position;\r\n\r\n let cwA = posA.relativeClockwise(posB, vertex.position);\r\n\r\n // If the second priority is clockwise from the first, the ligands are drawn clockwise, since\r\n // The hydrogen can be drawn on either side\r\n let isCw = cwA === -1;\r\n\r\n let rotation = vertex.value.bracket.chirality === '@' ? -1 : 1;\r\n let rs = MathHelper.parityOfPermutation(order) * rotation === 1 ? 'R' : 'S';\r\n\r\n // Flip the hydrogen direction when the drawing doesn't match the chirality.\r\n let wedgeA = 'down';\r\n let wedgeB = 'up';\r\n if (isCw && rs !== 'R' || !isCw && rs !== 'S') {\r\n vertex.value.hydrogenDirection = 'up';\r\n wedgeA = 'up';\r\n wedgeB = 'down';\r\n }\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, neighbours[order[order.length - 1]]).wedge = wedgeA;\r\n }\r\n\r\n // Get the shortest subtree to flip up / down. Ignore lowest priority\r\n // The rules are following:\r\n // 1. Do not draw wedge between two stereocenters\r\n // 2. Heteroatoms\r\n // 3. Draw outside ring\r\n // 4. Shortest subtree\r\n\r\n let wedgeOrder = new Array(neighbours.length - 1);\r\n let showHydrogen = vertex.value.rings.length > 1 && vertex.value.hasHydrogen;\r\n let offset = vertex.value.hasHydrogen ? 1 : 0;\r\n\r\n for (let j = 0; j < order.length - offset; j++) {\r\n wedgeOrder[j] = new Uint32Array(2);\r\n let neighbour = this.graph.vertices[neighbours[order[j]]];\r\n wedgeOrder[j][0] += neighbour.value.isStereoCenter ? 0 : 100000;\r\n // wedgeOrder[j][0] += neighbour.value.rings.length > 0 ? 0 : 10000;\r\n // Only add if in same ring, unlike above\r\n wedgeOrder[j][0] += this.areVerticesInSameRing(neighbour, vertex) ? 0 : 10000;\r\n wedgeOrder[j][0] += neighbour.value.isHeteroAtom() ? 1000 : 0;\r\n wedgeOrder[j][0] -= neighbour.value.subtreeDepth === 0 ? 1000 : 0;\r\n wedgeOrder[j][0] += 1000 - neighbour.value.subtreeDepth;\r\n wedgeOrder[j][1] = neighbours[order[j]];\r\n }\r\n\r\n\r\n wedgeOrder.sort(function (a, b) {\r\n if (a[0] > b[0]) {\r\n return -1;\r\n } else if (a[0] < b[0]) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n\r\n // If all neighbours are in a ring, do not draw wedge, the hydrogen will be drawn.\r\n if (!showHydrogen) {\r\n let wedgeId = wedgeOrder[0][1];\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedgeB;\r\n } else {\r\n let wedge = wedgeB;\r\n\r\n for (let j = order.length - 1; j >= 0; j--) {\r\n if (wedge === wedgeA) {\r\n wedge = wedgeB;\r\n } else {\r\n wedge = wedgeA;\r\n }\r\n if (neighbours[order[j]] === wedgeId) {\r\n break;\r\n }\r\n }\r\n\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedge;\r\n }\r\n }\r\n\r\n vertex.value.chirality = rs;\r\n }\r\n }\r\n\r\n /**\r\n *\r\n *\r\n * @param {Number} vertexId The id of a vertex.\r\n * @param {(Number|null)} previousVertexId The id of the parent vertex of the vertex.\r\n * @param {Uint8Array} visited An array containing the visited flag for all vertices in the graph.\r\n * @param {Array} priority An array of arrays storing the atomic numbers for each level.\r\n * @param {Number} maxDepth The maximum depth.\r\n * @param {Number} depth The current depth.\r\n * @param {Number} parentAtomicNumber\r\n */\r\n visitStereochemistry(vertexId, previousVertexId, visited, priority, maxDepth, depth, parentAtomicNumber = 0) {\r\n visited[vertexId] = 1;\r\n let vertex = this.graph.vertices[vertexId];\r\n let atomicNumber = vertex.value.getAtomicNumber();\r\n\r\n if (priority.length <= depth) {\r\n priority.push(Array());\r\n }\r\n\r\n for (let i = 0; i < this.graph.getEdge(vertexId, previousVertexId).weight; i++) {\r\n priority[depth].push(parentAtomicNumber * 1000 + atomicNumber);\r\n }\r\n\r\n let neighbours = this.graph.vertices[vertexId].neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (visited[neighbours[i]] !== 1 && depth < maxDepth - 1) {\r\n this.visitStereochemistry(neighbours[i], vertexId, visited.slice(), priority, maxDepth, depth + 1, atomicNumber);\r\n }\r\n }\r\n\r\n // Valences are filled with hydrogens and passed to the next level.\r\n if (depth < maxDepth - 1) {\r\n let bonds = 0;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n bonds += this.graph.getEdge(vertexId, neighbours[i]).weight;\r\n }\r\n\r\n for (let i = 0; i < vertex.value.getMaxBonds() - bonds; i++) {\r\n if (priority.length <= depth + 1) {\r\n priority.push(Array());\r\n }\r\n\r\n priority[depth + 1].push(atomicNumber * 1000 + 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Creates pseudo-elements (such as Et, Me, Ac, Bz, ...) at the position of the carbon sets\r\n * the involved atoms not to be displayed.\r\n */\r\n initPseudoElements() {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n // Ignore atoms that have less than 3 neighbours, except if\r\n // the vertex is connected to a ring and has two neighbours\r\n if (vertex.getNeighbourCount() < 3 || vertex.value.rings.length > 0) {\r\n continue;\r\n }\r\n\r\n // TODO: This exceptions should be handled more elegantly (via config file?)\r\n\r\n // Ignore phosphates (especially for triphosphates)\r\n if (vertex.value.element === 'P') {\r\n continue;\r\n }\r\n\r\n // Ignore also guanidine\r\n if (vertex.value.element === 'C' && neighbours.length === 3 &&\r\n neighbours[0].value.element === 'N' && neighbours[1].value.element === 'N' && neighbours[2].value.element === 'N') {\r\n continue;\r\n }\r\n\r\n // Continue if there are less than two heteroatoms\r\n // or if a neighbour has more than 1 neighbour\r\n let heteroAtomCount = 0;\r\n let ctn = 0;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n let neighbouringElement = neighbour.value.element;\r\n let neighbourCount = neighbour.getNeighbourCount();\r\n\r\n if (neighbouringElement !== 'C' && neighbouringElement !== 'H' &&\r\n neighbourCount === 1) {\r\n heteroAtomCount++;\r\n }\r\n\r\n if (neighbourCount > 1) {\r\n ctn++;\r\n }\r\n }\r\n\r\n if (ctn > 1 || heteroAtomCount < 2) {\r\n continue;\r\n }\r\n\r\n // Get the previous atom (the one which is not terminal)\r\n let previous = null;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n previous = neighbour;\r\n }\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n continue;\r\n }\r\n\r\n neighbour.value.isDrawn = false;\r\n\r\n let hydrogens = Atom.maxBonds[neighbour.value.element] - neighbour.value.bondCount;\r\n let charge = '';\r\n\r\n if (neighbour.value.bracket) {\r\n hydrogens = neighbour.value.bracket.hcount;\r\n charge = neighbour.value.bracket.charge || 0;\r\n }\r\n\r\n vertex.value.attachPseudoElement(neighbour.value.element, previous ? previous.value.element : null, hydrogens, charge);\r\n }\r\n }\r\n\r\n // The second pass\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const atom = vertex.value;\r\n const element = atom.element;\r\n\r\n if (element === 'C' || element === 'H' || !atom.isDrawn) {\r\n continue;\r\n }\r\n\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j].value;\r\n\r\n if (!neighbour.hasAttachedPseudoElements || neighbour.getAttachedPseudoElementsCount() !== 2) {\r\n continue;\r\n }\r\n\r\n const pseudoElements = neighbour.getAttachedPseudoElements();\r\n\r\n if (pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\r\n neighbour.isDrawn = false;\r\n vertex.value.attachPseudoElement('Ac', '', 0);\r\n }\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.graph.getDecays();\r\n }\r\n\r\n buildBlockSmiles() {\r\n return this.graph.buildSmiles();\r\n }\r\n\r\n /**\r\n * Find edge and mark it as decay point and redraw graph\r\n * @param e event\r\n */\r\n handleMouseClick(e) {\r\n if (this.opts.drawDecayPoints === DecayState.VALUES.NO) {\r\n return;\r\n }\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (!this.graph) {\r\n return;\r\n }\r\n this.findAndReDrawEdge(e.clientX - this.opts.offsetX, e.clientY - this.opts.offsetY + (document.documentElement.scrollTop || document.body.scrollTop));\r\n }\r\n\r\n /**\r\n * Find edge which was clicked, mark edge as decay point and redraw graph\r\n * @param mouseX mouse positionX - offsetX\r\n * @param mouseY mouse positionY - offsetY\r\n */\r\n findAndReDrawEdge(mouseX, mouseY) {\r\n for (let i = 0; i < this.graph.edges.length; ++i) {\r\n let vertexA = this.graph.vertices[this.graph.edges[i].sourceId];\r\n let vertexB = this.graph.vertices[this.graph.edges[i].targetId];\r\n if (!vertexA || !vertexB) {\r\n continue;\r\n }\r\n let scale = this.computeScale();\r\n let line = new Line(vertexA.position, vertexB.position, null, null, false, false, true);\r\n let l = this.computeEdgeLeftPoint(line, scale);\r\n let r = this.computeEdgeRightPoint(line, scale);\r\n if (mouseX < l.x - this.opts.mouseTolerance || mouseX > r.x + this.opts.mouseTolerance) {\r\n continue;\r\n }\r\n if ((mouseY > l.y - this.opts.mouseTolerance && mouseY < r.y + this.opts.mouseTolerance)\r\n || (mouseY > r.y - this.opts.mouseTolerance && mouseY < l.y + this.opts.mouseTolerance)) {\r\n this.reDrawGraphWithEdgeAsDecay(i);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Make edge decay point and redraw graph\r\n * @param {Number} edgeId\r\n */\r\n reDrawGraphWithEdgeAsDecay(edgeId) {\r\n this.graph.revertEdgeDecayPoint(edgeId);\r\n this.canvasWrapper.updateSize(this.opts.width, this.opts.height);\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n }\r\n\r\n /**\r\n * Compute scale of canvas\r\n * @return {number} scale\r\n */\r\n computeScale() {\r\n let scaleX = this.canvasWrapper.canvas.offsetWidth / this.canvasWrapper.drawingWidth;\r\n let scaleY = this.canvasWrapper.canvas.offsetHeight / this.canvasWrapper.drawingHeight;\r\n return (scaleX < scaleY) ? scaleX : scaleY;\r\n }\r\n\r\n /**\r\n * Compute left point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeLeftPoint(line, scale) {\r\n return this.computeEdgePoint(line.getLeftVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute right point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeRightPoint(line, scale) {\r\n return this.computeEdgePoint(line.getRightVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute point coordinates for compare\r\n * add offset to coordinates and multiply coordinates with scale\r\n * @param {Vector2} point\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgePoint(point, scale) {\r\n point.x += this.canvasWrapper.offsetX;\r\n point.y += this.canvasWrapper.offsetY;\r\n point.x *= scale;\r\n point.y *= scale;\r\n return point;\r\n }\r\n}\r\n\r\nmodule.exports = Drawer;\r\n","//@ts-check\r\n\r\n/** \r\n * A class representing an edge. \r\n * \r\n * @property {Number} id The id of this edge.\r\n * @property {Number} sourceId The id of the source vertex.\r\n * @property {Number} targetId The id of the target vertex.\r\n * @property {Number} weight The weight of this edge. That is, the degree of the bond (single bond = 1, double bond = 2, etc).\r\n * @property {String} [bondType='-'] The bond type of this edge.\r\n * @property {Boolean} [isPartOfAromaticRing=false] Whether or not this edge is part of an aromatic ring.\r\n * @property {Boolean} [center=false] Wheter or not the bond is centered. For example, this affects straight double bonds.\r\n * @property {String} [wedge=''] Wedge direction. Either '', 'up' or 'down'\r\n */\r\nclass Edge {\r\n /**\r\n * The constructor for the class Edge.\r\n *\r\n * @param {Number} sourceId A vertex id.\r\n * @param {Number} targetId A vertex id.\r\n * @param {Number} [weight=1] The weight of the edge.\r\n */\r\n constructor(sourceId, targetId, weight = 1) {\r\n this.id = null;\r\n this.sourceId = sourceId;\r\n this.targetId = targetId;\r\n this.weight = weight;\r\n this.bondType = '-';\r\n this.isPartOfAromaticRing = false;\r\n this.center = false;\r\n this.wedge = '';\r\n this.isDecay = false;\r\n this.isDecayAll = false;\r\n }\r\n\r\n /**\r\n * Set the bond type of this edge. This also sets the edge weight.\r\n * @param {String} bondType \r\n */\r\n setBondType(bondType) {\r\n this.bondType = bondType;\r\n this.weight = Edge.bonds[bondType];\r\n }\r\n\r\n /**\r\n * Set decay\r\n * @param {Boolean} decay point\r\n */\r\n setDecay(decay) {\r\n this.isDecay = decay;\r\n }\r\n\r\n /**\r\n * Set decay All\r\n * @param {Boolean} decay point\r\n */\r\n setDecayAll(decay) {\r\n this.isDecayAll = decay;\r\n }\r\n\r\n /**\r\n * An object mapping the bond type to the number of bonds.\r\n *\r\n * @returns {Object} The object containing the map.\r\n */\r\n static get bonds() {\r\n return {\r\n '-': 1,\r\n '/': 1,\r\n '\\\\': 1,\r\n '=': 2,\r\n '#': 3,\r\n '$': 4\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Edge;\r\n","//@ts-check\r\nconst DecayPoint = require('./DecayPoint');\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Ring = require('./Ring');\r\nconst Atom = require('./Atom');\r\nconst VertexState = require('./VertexState');\r\nconst SmallGraph = require('./SmallGraph');\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst DecayState = require('./DecayState');\r\nconst MutableBoolean = require('./MutableBoolean');\r\nconst MutableCounter = require('./MutableCounter');\r\nconst Direction = require('./Direction');\r\n\r\n/**\r\n * A class representing the molecular graph.\r\n *\r\n * @property {Vertex[]} vertices The vertices of the graph.\r\n * @property {Edge[]} edges The edges of this graph.\r\n * @property {Number[]} decays The id of edges marked as decay point of this graph.\r\n * @property {Object} vertexIdsToEdgeId A map mapping vertex ids to the edge between the two vertices. The key is defined as vertexAId + '_' + vertexBId.\r\n * @property {Boolean} isometric A boolean indicating whether or not the SMILES associated with this graph is isometric.\r\n */\r\nclass Graph {\r\n /**\r\n * The constructor of the class Graph.\r\n *\r\n * @param {Object} parseTree A SMILES parse tree.\r\n * @param {Boolean} [isomeric=false] A boolean specifying whether or not the SMILES is isomeric.\r\n * @param options\r\n */\r\n constructor(parseTree, isomeric = false, options = {}) {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.decays = Array();\r\n this.decaysAll = Array();\r\n this.vertexIdsToEdgeId = {};\r\n this.isomeric = isomeric;\r\n this._startingVertexes = [];\r\n this._isCyclic = false;\r\n this._polyketide = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.options = options;\r\n this._componentsIsPolyketide = [];\r\n\r\n // Used for the bridge detection algorithm\r\n this._time = 0;\r\n this._init(parseTree);\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION. Initializing the graph from the parse tree.\r\n *\r\n * @param {Object} node The current node in the parse tree.\r\n * @param order\r\n * @param {Number} parentVertexId=null The id of the previous vertex.\r\n * @param {Boolean} isBranch=false Whether or not the bond leading to this vertex is a branch bond. Branches are represented by parentheses in smiles (e.g. CC(O)C).\r\n */\r\n _init(node, order = 0, parentVertexId = null, isBranch = false) {\r\n // Create a new vertex object\r\n let atom = new Atom(node.atom.element ? node.atom.element : node.atom, node.bond);\r\n\r\n atom.branchBond = node.branchBond;\r\n atom.ringbonds = node.ringbonds;\r\n atom.bracket = node.atom.element ? node.atom : null;\r\n\r\n let vertex = new Vertex(atom);\r\n let parentVertex = this.vertices[parentVertexId];\r\n\r\n this.addVertex(vertex);\r\n\r\n // Add the id of this node to the parent as child\r\n if (parentVertexId !== null) {\r\n vertex.setParentVertexId(parentVertexId);\r\n vertex.value.addNeighbouringElement(parentVertex.value.element);\r\n parentVertex.addChild(vertex.id);\r\n parentVertex.value.addNeighbouringElement(atom.element);\r\n\r\n // In addition create a spanningTreeChildren property, which later will\r\n // not contain the children added through ringbonds\r\n parentVertex.spanningTreeChildren.push(vertex.id);\r\n\r\n // Add edge between this node and its parent\r\n let edge = new Edge(parentVertexId, vertex.id, 1);\r\n let vertexId;\r\n\r\n if (isBranch) {\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n } else {\r\n edge.setBondType(parentVertex.value.bondType || '-');\r\n vertexId = parentVertex.id;\r\n }\r\n\r\n this.addEdge(edge);\r\n }\r\n\r\n let offset = node.ringbondCount + 1;\r\n\r\n if (atom.bracket) {\r\n offset += atom.bracket.hcount;\r\n }\r\n\r\n let stereoHydrogens = 0;\r\n if (atom.bracket && atom.bracket.chirality) {\r\n atom.isStereoCenter = true;\r\n stereoHydrogens = atom.bracket.hcount;\r\n for (var i = 0; i < stereoHydrogens; i++) {\r\n this._init({\r\n atom: 'H',\r\n isBracket: 'false',\r\n branches: Array(),\r\n branchCount: 0,\r\n ringbonds: Array(),\r\n ringbondCount: false,\r\n next: null,\r\n hasNext: false,\r\n bond: '-'\r\n }, i, vertex.id, true);\r\n }\r\n }\r\n\r\n for (var i = 0; i < node.branchCount; i++) {\r\n this._init(node.branches[i], i + offset, vertex.id, true);\r\n }\r\n\r\n if (node.hasNext) {\r\n this._init(node.next, node.branchCount + offset, vertex.id);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of molecule\r\n * Types of decay points, declared in DecayPoint\r\n */\r\n findDecayPoints() {\r\n if (!Object.keys(this.options).length) {\r\n return;\r\n }\r\n\r\n switch (this.options.drawDecayPoints) {\r\n default:\r\n case DecayState.VALUES.NO:\r\n return;\r\n case DecayState.VALUES.STANDARD:\r\n this.standardDecays();\r\n break;\r\n case DecayState.VALUES.SOURCE:\r\n this.sourceDecays();\r\n break;\r\n case DecayState.VALUES.STANDARD_AND_SOURCE:\r\n this.standardDecays();\r\n this.sourceDecays();\r\n break;\r\n }\r\n }\r\n\r\n reduceDecays() {\r\n this._decaysCopy = [];\r\n this.dfsSmilesInitialization();\r\n for (let i = 0; i < this.decays.length; i++) {\r\n this.smallBlockDfsStart(this.edges[this.decays[i]]);\r\n }\r\n this.decays = [];\r\n this.decays = this._decaysCopy;\r\n this.setStandardDecays();\r\n }\r\n\r\n dfsSmallInitialization(vertices) {\r\n for (let i = 0; i < vertices.length; ++i) {\r\n this.vertices[vertices[i]].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n smallBlockDfsStart(edge) {\r\n let stackVisitedVertexes = [];\r\n let depth = this.smallDfs(this.vertices[edge.sourceId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n stackVisitedVertexes = [];\r\n depth = this.smallDfs(this.vertices[edge.targetId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n this._decaysCopy.push(edge.id);\r\n }\r\n }\r\n }\r\n\r\n smallDfs(vertex, depth, stackVisitedVertexes) {\r\n stackVisitedVertexes.push(vertex.id);\r\n if (depth > 3) {\r\n return depth;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return depth;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n ++depth;\r\n\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n depth = this.smallDfs(this.vertices[nextVertex], depth, stackVisitedVertexes);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n return depth;\r\n }\r\n\r\n setStandardDecays() {\r\n this.edges.forEach(e => {\r\n e.setDecay(false);\r\n });\r\n this.decays.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n });\r\n }\r\n\r\n standardDecays() {\r\n for (let i = 0; i < this.edges.length; i++) {\r\n if (this.edges[i].bondType === '=') {\r\n let dec = this.isDecayPoint(this.edges[i].sourceId, this.edges[i].targetId, i);\r\n if (dec !== false) {\r\n this.edges[dec].setDecay(true);\r\n this.decays.push(dec);\r\n this.edges[dec].setDecayAll(true);\r\n this.decaysAll.push(dec);\r\n }\r\n }\r\n }\r\n this.reduceDecays();\r\n }\r\n\r\n sourceDecays() {\r\n this.options.decaySource.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n this.edges[e].setDecayAll(true);\r\n this.decays.push(e);\r\n this.decaysAll.push(e);\r\n });\r\n }\r\n\r\n /**\r\n * check if its decay point of specific decay types\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @param decayTypes DecayPoint\r\n * @returns {int|boolean} return edge id when found, otherwise return false\r\n */\r\n isDecayPoint(sourceId, targetId, edgeBondId, decayTypes = DecayPoint.VALUES.ALL) {\r\n switch (decayTypes) {\r\n case DecayPoint.VALUES.ALL:\r\n let found = this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n if (found === false) {\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n } else {\r\n return found;\r\n }\r\n case DecayPoint.VALUES.COO:\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n case DecayPoint.VALUES.CONH:\r\n return this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-O- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'O', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'O', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-NH- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'N', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'N', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay point edge id of right neighbour\r\n * @param vertexId\r\n * @param element\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayId(vertexId, element, edgeBondId) {\r\n for (let i = 0; i < this.vertices[vertexId].edges.length; i++) {\r\n let edgeId = this.checkNeighbourEdgeId(this.vertices[vertexId].edges[i], vertexId, element);\r\n if (edgeId !== false && edgeId !== edgeBondId) {\r\n return edgeId;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find edge id of decay point\r\n * @param edgeId\r\n * @param vertexId\r\n * @param element\r\n * @returns {int|boolean}\r\n */\r\n checkNeighbourEdgeId(edgeId, vertexId, element) {\r\n if ((this.edges[edgeId].sourceId === vertexId && this.vertices[this.edges[edgeId].targetId].value.element === element) ||\r\n (this.edges[edgeId].targetId === vertexId && this.vertices[this.edges[edgeId].sourceId].value.element === element)) {\r\n return edgeId;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clears all the elements in this graph (edges and vertices).\r\n */\r\n clear() {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.vertexIdsToEdgeId = {};\r\n }\r\n\r\n /**\r\n * Add a vertex to the graph.\r\n *\r\n * @param {Vertex} vertex A new vertex.\r\n * @returns {Number} The vertex id of the new vertex.\r\n */\r\n addVertex(vertex) {\r\n vertex.id = this.vertices.length;\r\n this.vertices.push(vertex);\r\n\r\n return vertex.id;\r\n }\r\n\r\n /**\r\n * Add an edge to the graph.\r\n *\r\n * @param {Edge} edge A new edge.\r\n * @returns {Number} The edge id of the new edge.\r\n */\r\n addEdge(edge) {\r\n let source = this.vertices[edge.sourceId];\r\n let target = this.vertices[edge.targetId];\r\n\r\n edge.id = this.edges.length;\r\n this.edges.push(edge);\r\n\r\n this.vertexIdsToEdgeId[edge.sourceId + '_' + edge.targetId] = edge.id;\r\n this.vertexIdsToEdgeId[edge.targetId + '_' + edge.sourceId] = edge.id;\r\n edge.isPartOfAromaticRing = source.value.isPartOfAromaticRing && target.value.isPartOfAromaticRing;\r\n\r\n source.value.bondCount += edge.weight;\r\n target.value.bondCount += edge.weight;\r\n\r\n source.edges.push(edge.id);\r\n target.edges.push(edge.id);\r\n\r\n return edge.id;\r\n }\r\n\r\n /**\r\n * Returns the edge between two given vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {(Edge|null)} The edge or, if no edge can be found, null.\r\n */\r\n getEdge(vertexIdA, vertexIdB) {\r\n let edgeId = this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB];\r\n\r\n return edgeId === undefined ? null : this.edges[edgeId];\r\n }\r\n\r\n /**\r\n * Returns the ids of edges connected to a vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Number[]} An array containing the ids of edges connected to the vertex.\r\n */\r\n getEdges(vertexId) {\r\n let edgeIds = Array();\r\n let vertex = this.vertices[vertexId];\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n edgeIds.push(this.vertexIdsToEdgeId[vertexId + '_' + vertex.neighbours[i]]);\r\n }\r\n\r\n return edgeIds;\r\n }\r\n\r\n\r\n /**\r\n * Check whether or not two vertices are connected by an edge.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not two vertices are connected by an edge.\r\n */\r\n hasEdge(vertexIdA, vertexIdB) {\r\n return this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB] !== undefined\r\n }\r\n\r\n /**\r\n * Returns an array containing the vertex ids of this graph.\r\n *\r\n * @returns {Number[]} An array containing all vertex ids of this graph.\r\n */\r\n getVertexList() {\r\n let arr = [this.vertices.length];\r\n\r\n for (var i = 0; i < this.vertices.length; i++) {\r\n arr[i] = this.vertices[i].id;\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array containing source, target arrays of this graphs edges.\r\n *\r\n * @returns {Array[]} An array containing source, target arrays of this graphs edges. Example: [ [ 2, 5 ], [ 6, 9 ] ].\r\n */\r\n getEdgeList() {\r\n let arr = Array(this.edges.length);\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n arr[i] = [this.edges[i].sourceId, this.edges[i].targetId];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph.\r\n */\r\n getAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph with all bridges removed (thus the components). Thus the remaining vertices are all part of ring systems.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph with all bridges removed.\r\n */\r\n getComponentsAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n let bridges = this.getBridges();\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n for (var i = 0; i < bridges.length; i++) {\r\n adjacencyMatrix[bridges[i][0]][bridges[i][1]] = 0;\r\n adjacencyMatrix[bridges[i][1]][bridges[i][0]] = 0;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency matrix of the subgraph.\r\n */\r\n getSubgraphAdjacencyMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyMatrix[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of the graph.\r\n *\r\n * @returns {Array[]} The distance matrix of the graph.\r\n */\r\n getDistanceMatrix() {\r\n let length = this.vertices.length;\r\n let adja = this.getAdjacencyMatrix();\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The distance matrix of the subgraph.\r\n */\r\n getSubgraphDistanceMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adja = this.getSubgraphAdjacencyMatrix(vertexIds);\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of the graph.\r\n *\r\n * @returns {Array[]} The adjancency list of the graph.\r\n */\r\n getAdjacencyList() {\r\n let length = this.vertices.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = [];\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(this.vertices[i].id, this.vertices[j].id)) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency list of the subgraph.\r\n */\r\n getSubgraphAdjacencyList(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = Array();\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Returns an array containing the edge ids of bridges. A bridge splits the graph into multiple components when removed.\r\n *\r\n * @returns {Number[]} An array containing the edge ids of the bridges.\r\n */\r\n getBridges() {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n let disc = new Array(length);\r\n let low = new Array(length);\r\n let parent = new Array(length);\r\n let adj = this.getAdjacencyList();\r\n let outBridges = Array();\r\n\r\n visited.fill(false);\r\n parent.fill(null);\r\n this._time = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (!visited[i]) {\r\n this._bridgeDfs(i, visited, disc, low, parent, adj, outBridges);\r\n }\r\n }\r\n\r\n return outBridges;\r\n }\r\n\r\n /**\r\n * Traverses the graph in breadth-first order.\r\n *\r\n * @param {Number} startVertexId The id of the starting vertex.\r\n * @param {Function} callback The callback function to be called on every vertex.\r\n */\r\n traverseBF(startVertexId, callback) {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n\r\n visited.fill(false);\r\n\r\n var queue = [startVertexId];\r\n\r\n while (queue.length > 0) {\r\n // JavaScripts shift() is O(n) ... bad JavaScript, bad!\r\n let u = queue.shift();\r\n let vertex = this.vertices[u];\r\n\r\n callback(vertex);\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n let v = vertex.neighbours[i];\r\n if (!visited[v]) {\r\n visited[v] = true;\r\n queue.push(v);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the depth of a subtree in the direction opposite to the vertex specified as the parent vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId The id of a neighbouring vertex.\r\n * @returns {Number} The depth of the sub-tree.\r\n */\r\n getTreeDepth(vertexId, parentVertexId) {\r\n if (vertexId === null || parentVertexId === null) {\r\n return 0;\r\n }\r\n\r\n let neighbours = this.vertices[vertexId].getSpanningTreeNeighbours(parentVertexId);\r\n let max = 0;\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n let childId = neighbours[i];\r\n let d = this.getTreeDepth(childId, vertexId);\r\n\r\n if (d > max) {\r\n max = d;\r\n }\r\n }\r\n\r\n return max + 1;\r\n }\r\n\r\n /**\r\n * Traverse a sub-tree in the graph.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId A neighbouring vertex.\r\n * @param {Function} callback The callback function that is called with each visited as an argument.\r\n * @param {Number} [maxDepth=999999] The maximum depth of the recursion.\r\n * @param {Boolean} [ignoreFirst=false] Whether or not to ignore the starting vertex supplied as vertexId in the callback.\r\n * @param {Number} [depth=1] The current depth in the tree.\r\n * @param {Uint8Array} [visited=null] An array holding a flag on whether or not a node has been visited.\r\n */\r\n traverseTree(vertexId, parentVertexId, callback, maxDepth = 999999, ignoreFirst = false, depth = 1, visited = null) {\r\n if (visited === null) {\r\n visited = new Uint8Array(this.vertices.length);\r\n }\r\n\r\n if (depth > maxDepth + 1 || visited[vertexId] === 1) {\r\n return;\r\n }\r\n\r\n visited[vertexId] = 1;\r\n\r\n let vertex = this.vertices[vertexId];\r\n let neighbours = vertex.getNeighbours(parentVertexId);\r\n\r\n if (!ignoreFirst || depth > 1) {\r\n callback(vertex);\r\n }\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n this.traverseTree(neighbours[i], vertexId, callback, maxDepth, ignoreFirst, depth + 1, visited);\r\n }\r\n }\r\n\r\n /**\r\n * Positiones the (sub)graph using Kamada and Kawais algorithm for drawing general undirected graphs. https://pdfs.semanticscholar.org/b8d3/bca50ccc573c5cb99f7d201e8acce6618f04.pdf\r\n * There are undocumented layout parameters. They are undocumented for a reason, so be very careful.\r\n *\r\n * @param {Number[]} vertexIds An array containing vertexIds to be placed using the force based layout.\r\n * @param {Vector2} center The center of the layout.\r\n * @param {Number} startVertexId A vertex id. Should be the starting vertex - e.g. the first to be positioned and connected to a previously place vertex.\r\n * @param {Ring} ring The bridged ring associated with this force-based layout.\r\n */\r\n kkLayout(vertexIds, center, startVertexId, ring, bondLength,\r\n threshold = 0.1, innerThreshold = 0.1, maxIteration = 2000,\r\n maxInnerIteration = 50, maxEnergy = 1e9) {\r\n\r\n let edgeStrength = bondLength;\r\n\r\n // Add vertices that are directly connected to the ring\r\n var i = vertexIds.length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n var j = vertex.neighbours.length;\r\n }\r\n\r\n let matDist = this.getSubgraphDistanceMatrix(vertexIds);\r\n let length = vertexIds.length;\r\n\r\n // Initialize the positions. Place all vertices on a ring around the center\r\n let radius = MathHelper.polyCircumradius(500, length);\r\n let angle = MathHelper.centralAngle(length);\r\n let a = 0.0;\r\n let arrPositionX = new Float32Array(length);\r\n let arrPositionY = new Float32Array(length);\r\n let arrPositioned = Array(length);\r\n\r\n i = length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n if (!vertex.positioned) {\r\n arrPositionX[i] = center.x + Math.cos(a) * radius;\r\n arrPositionY[i] = center.y + Math.sin(a) * radius;\r\n } else {\r\n arrPositionX[i] = vertex.position.x;\r\n arrPositionY[i] = vertex.position.y;\r\n }\r\n arrPositioned[i] = vertex.positioned;\r\n a += angle;\r\n }\r\n\r\n // Create the matrix containing the lengths\r\n let matLength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matLength[i] = new Array(length);\r\n var j = length;\r\n while (j--) {\r\n matLength[i][j] = bondLength * matDist[i][j];\r\n }\r\n }\r\n\r\n // Create the matrix containing the spring strenghts\r\n let matStrength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matStrength[i] = Array(length);\r\n var j = length;\r\n while (j--) {\r\n matStrength[i][j] = edgeStrength * Math.pow(matDist[i][j], -2.0);\r\n }\r\n }\r\n\r\n // Create the matrix containing the energies\r\n let matEnergy = Array(length);\r\n let arrEnergySumX = new Float32Array(length);\r\n let arrEnergySumY = new Float32Array(length);\r\n i = length;\r\n while (i--) {\r\n matEnergy[i] = Array(length);\r\n }\r\n\r\n i = length;\r\n let ux, uy, dEx, dEy, vx, vy, denom;\r\n\r\n while (i--) {\r\n ux = arrPositionX[i];\r\n uy = arrPositionY[i];\r\n dEx = 0.0;\r\n dEy = 0.0;\r\n let j = length;\r\n while (j--) {\r\n if (i === j) {\r\n continue;\r\n }\r\n vx = arrPositionX[j];\r\n vy = arrPositionY[j];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n matEnergy[i][j] = [\r\n matStrength[i][j] * ((ux - vx) - matLength[i][j] * (ux - vx) * denom),\r\n matStrength[i][j] * ((uy - vy) - matLength[i][j] * (uy - vy) * denom)\r\n ];\r\n matEnergy[j][i] = matEnergy[i][j];\r\n dEx += matEnergy[i][j][0];\r\n dEy += matEnergy[i][j][1];\r\n }\r\n arrEnergySumX[i] = dEx;\r\n arrEnergySumY[i] = dEy;\r\n }\r\n\r\n // Utility functions, maybe inline them later\r\n let energy = function (index) {\r\n return [arrEnergySumX[index] * arrEnergySumX[index] + arrEnergySumY[index] * arrEnergySumY[index], arrEnergySumX[index], arrEnergySumY[index]];\r\n };\r\n\r\n let highestEnergy = function () {\r\n let maxEnergy = 0.0;\r\n let maxEnergyId = 0;\r\n let maxDEX = 0.0;\r\n let maxDEY = 0.0;\r\n\r\n i = length;\r\n while (i--) {\r\n let [delta, dEX, dEY] = energy(i);\r\n\r\n if (delta > maxEnergy && arrPositioned[i] === false) {\r\n maxEnergy = delta;\r\n maxEnergyId = i;\r\n maxDEX = dEX;\r\n maxDEY = dEY;\r\n }\r\n }\r\n\r\n return [maxEnergyId, maxEnergy, maxDEX, maxDEY];\r\n };\r\n\r\n let update = function (index, dEX, dEY) {\r\n let dxx = 0.0;\r\n let dyy = 0.0;\r\n let dxy = 0.0;\r\n let ux = arrPositionX[index];\r\n let uy = arrPositionY[index];\r\n let arrL = matLength[index];\r\n let arrK = matStrength[index];\r\n\r\n i = length;\r\n while (i--) {\r\n if (i === index) {\r\n continue;\r\n }\r\n\r\n let vx = arrPositionX[i];\r\n let vy = arrPositionY[i];\r\n let l = arrL[i];\r\n let k = arrK[i];\r\n let m = (ux - vx) * (ux - vx);\r\n let denom = 1.0 / Math.pow(m + (uy - vy) * (uy - vy), 1.5);\r\n\r\n dxx += k * (1 - l * (uy - vy) * (uy - vy) * denom);\r\n dyy += k * (1 - l * m * denom);\r\n dxy += k * (l * (ux - vx) * (uy - vy) * denom);\r\n }\r\n\r\n // Prevent division by zero\r\n if (dxx === 0) {\r\n dxx = 0.1;\r\n }\r\n\r\n if (dyy === 0) {\r\n dyy = 0.1;\r\n }\r\n\r\n if (dxy === 0) {\r\n dxy = 0.1;\r\n }\r\n\r\n let dy = (dEX / dxx + dEY / dxy);\r\n dy /= (dxy / dxx - dyy / dxy); // had to split this onto two lines because the syntax highlighter went crazy.\r\n let dx = -(dxy * dy + dEX) / dxx;\r\n\r\n arrPositionX[index] += dx;\r\n arrPositionY[index] += dy;\r\n\r\n // Update the energies\r\n let arrE = matEnergy[index];\r\n dEX = 0.0;\r\n dEY = 0.0;\r\n\r\n ux = arrPositionX[index];\r\n uy = arrPositionY[index];\r\n\r\n let vx, vy, prevEx, prevEy, denom;\r\n\r\n i = length;\r\n while (i--) {\r\n if (index === i) {\r\n continue;\r\n }\r\n vx = arrPositionX[i];\r\n vy = arrPositionY[i];\r\n // Store old energies\r\n prevEx = arrE[i][0];\r\n prevEy = arrE[i][1];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n dx = arrK[i] * ((ux - vx) - arrL[i] * (ux - vx) * denom);\r\n dy = arrK[i] * ((uy - vy) - arrL[i] * (uy - vy) * denom);\r\n\r\n arrE[i] = [dx, dy];\r\n dEX += dx;\r\n dEY += dy;\r\n arrEnergySumX[i] += dx - prevEx;\r\n arrEnergySumY[i] += dy - prevEy;\r\n }\r\n arrEnergySumX[index] = dEX;\r\n arrEnergySumY[index] = dEY;\r\n };\r\n\r\n // Setting up variables for the while loops\r\n let maxEnergyId = 0;\r\n let dEX = 0.0;\r\n let dEY = 0.0;\r\n let delta = 0.0;\r\n let iteration = 0;\r\n let innerIteration = 0;\r\n\r\n while (maxEnergy > threshold && maxIteration > iteration) {\r\n iteration++;\r\n [maxEnergyId, maxEnergy, dEX, dEY] = highestEnergy();\r\n delta = maxEnergy;\r\n innerIteration = 0;\r\n while (delta > innerThreshold && maxInnerIteration > innerIteration) {\r\n innerIteration++;\r\n update(maxEnergyId, dEX, dEY);\r\n [delta, dEX, dEY] = energy(maxEnergyId);\r\n }\r\n }\r\n\r\n i = length;\r\n while (i--) {\r\n let index = vertexIds[i];\r\n let vertex = this.vertices[index];\r\n vertex.position.x = arrPositionX[i];\r\n vertex.position.y = arrPositionY[i];\r\n vertex.positioned = true;\r\n vertex.forcePositioned = true;\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getBridges().\r\n */\r\n _bridgeDfs(u, visited, disc, low, parent, adj, outBridges) {\r\n visited[u] = true;\r\n disc[u] = low[u] = ++this._time;\r\n\r\n for (var i = 0; i < adj[u].length; i++) {\r\n let v = adj[u][i];\r\n\r\n if (!visited[v]) {\r\n parent[v] = u;\r\n\r\n this._bridgeDfs(v, visited, disc, low, parent, adj, outBridges);\r\n\r\n low[u] = Math.min(low[u], low[v]);\r\n\r\n // If low > disc, we have a bridge\r\n if (low[v] > disc[u]) {\r\n outBridges.push([u, v]);\r\n }\r\n } else if (v !== parent[u]) {\r\n low[u] = Math.min(low[u], disc[v]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the connected components of the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Set[]} Connected components as sets.\r\n */\r\n static getConnectedComponents(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let components = [];\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n let component = Array();\r\n visited[u] = true;\r\n component.push(u);\r\n count++;\r\n Graph._ccGetDfs(u, visited, adjacencyMatrix, component);\r\n if (component.length > 1) {\r\n components.push(component);\r\n }\r\n }\r\n }\r\n\r\n return components;\r\n }\r\n\r\n /**\r\n * Returns the number of connected components for the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of connected components of the supplied graph.\r\n */\r\n static getConnectedComponentCount(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n visited[u] = true;\r\n count++;\r\n Graph._ccCountDfs(u, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponentCount().\r\n */\r\n static _ccCountDfs(u, visited, adjacencyMatrix) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n Graph._ccCountDfs(v, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponents().\r\n */\r\n static _ccGetDfs(u, visited, adjacencyMatrix, component) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n component.push(v);\r\n Graph._ccGetDfs(v, visited, adjacencyMatrix, component);\r\n }\r\n }\r\n\r\n /**\r\n * Revert decay point value and update list of decay points\r\n * when edge isn't decay point -> change mark edge as decay point and add edge to decays list\r\n * when edge is decay point -> unmark edge as decay point and remove edgeId from list of decays\r\n * @param edgeId\r\n */\r\n revertEdgeDecayPoint(edgeId) {\r\n this.edges[edgeId].isDecay = !this.edges[edgeId].isDecay;\r\n this.edges[edgeId].isDecayAll = !this.edges[edgeId].isDecayAll;\r\n if (this.edges[edgeId].isDecay) {\r\n this.decays.push(edgeId);\r\n this.decaysAll.push(edgeId);\r\n } else {\r\n let index = this.decays.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decays.splice(index, 1);\r\n }\r\n index = this.decaysAll.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decaysAll.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.decays;\r\n }\r\n\r\n /**\r\n * Build block of SMILES based on decay points\r\n * DFS pass through graph\r\n * but the numbers are already setup in vertex.value.ringbonds array so no need to second pass of dfs\r\n */\r\n buildSmiles() {\r\n let smiles = [];\r\n this._polyketide = false;\r\n this.dfsSmilesInitialization();\r\n if (this.decays.length === 0) {\r\n this.startDfs(this.vertices[0], smiles);\r\n return {blockSmiles: smiles, sequence: '[0]', sequenceType: SequenceType.VALUES.OTHER, decays: this.decays, isPolyketide: this._polyketide};\r\n } else {\r\n this.dfsBuildSmilesStart(smiles);\r\n }\r\n this.dfsSmilesInitialization();\r\n this.dfsSmallStart();\r\n this._smallGraph.oneCyclic();\r\n this._smallGraph.dfsSequenceStart();\r\n let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence);\r\n return {\r\n blockSmiles: sequenceData.smiles,\r\n sequence: sequenceData.sequence,\r\n sequenceType: this._smallGraph.sequenceType + ((this._smallGraph.sequenceType === 'linear' || this._smallGraph.sequenceType === 'cyclic') && this._polyketide ? '-polyketide' : ''),\r\n decays: this.decays,\r\n isPolyketide: this._polyketide\r\n }\r\n }\r\n\r\n sortSequence(smiles, sequence) {\r\n let permutation = this.getSequencePermutation(sequence);\r\n let newSmiles = new Array(permutation.length).fill(null);\r\n for (let i = 0; i < permutation.length; ++i) {\r\n newSmiles[i] = smiles[permutation[i][0]];\r\n }\r\n\r\n let position = 0;\r\n let char = sequence.charAt(position);\r\n let newSequence = '';\r\n while (true) {\r\n switch (char) {\r\n case '0':\r\n case '1':\r\n case '2':\r\n case '3':\r\n case '4':\r\n case '5':\r\n case '6':\r\n case '7':\r\n case '8':\r\n case '9':\r\n let number = char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n while(!isNaN(char)) {\r\n number += char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n let j;\r\n for (j = 0; j < permutation.length; ++j) {\r\n if (permutation[j][0] === number) {\r\n newSequence += j;\r\n break;\r\n }\r\n }\r\n continue;\r\n default:\r\n newSequence += char;\r\n }\r\n\r\n ++position;\r\n if (position >= sequence.length) {\r\n break;\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n return {sequence: newSequence, smiles: newSmiles};\r\n }\r\n\r\n getSequencePermutation(sequence) {\r\n let re = /\\d+/g;\r\n let match = null;\r\n let permutation = [];\r\n while ((match = re.exec(sequence)) != null) {\r\n permutation.push(match);\r\n }\r\n return permutation;\r\n }\r\n\r\n dfsSmallStart() {\r\n this._smallGraph = new SmallGraph();\r\n for (let index = 0; index < this._startingVertexes.length; ++index) {\r\n this._smallGraph.addVertex(new Node(this._startingVertexes[index].component));\r\n this.first = this._startingVertexes[index];\r\n this.dfsSmall(this._startingVertexes[index], this._componentsIsPolyketide[index]);\r\n }\r\n }\r\n\r\n /**\r\n * Initialize graph for dfs\r\n * set for all vertices vertexState to NotFound\r\n */\r\n dfsSmilesInitialization() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n /**\r\n * Starting function for DFS\r\n * starts on decay points (on edge), so start on both side of edge\r\n * @param {Array} smiles output param, array of SMILES blocks (string)\r\n */\r\n dfsBuildSmilesStart(smiles) {\r\n this._cnt = 0;\r\n this._markComponent = false;\r\n this._startingVertexes = [];\r\n for (let i = 0; i < this.decays.length; ++i) {\r\n let edge = this.edges[this.decays[i]];\r\n this.markingComponents(this.startDfs(this.vertices[edge.sourceId], smiles));\r\n this.markingComponents(this.startDfs(this.vertices[edge.targetId], smiles));\r\n }\r\n }\r\n\r\n markingComponents(isPolyketyde) {\r\n if (this._markComponent) {\r\n this._cnt++;\r\n this._markComponent = false;\r\n this._componentsIsPolyketide.push(isPolyketyde);\r\n }\r\n }\r\n\r\n /**\r\n * Start DFS for build SMILES of blocks\r\n * @param {Vertex} vertex to start DFS\r\n * @param {Array} smiles output param, array od SMILES\r\n */\r\n startDfs(vertex, smiles) {\r\n let isPolyketide = new MutableBoolean(true);\r\n let decaysCounter = new MutableCounter();\r\n let vertexCounter = new MutableCounter();\r\n let through = [];\r\n let stackSmiles = [];\r\n this.first = vertex.id;\r\n this._isCyclic = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.dfsSmiles(vertex, stackSmiles, isPolyketide, decaysCounter, through, vertexCounter);\r\n if (decaysCounter.getValue() < 2 && isPolyketide.getValue() === true) {\r\n isPolyketide.setValue(through.every(vertex => vertex === 'O' || vertex === 'N') && vertexCounter.getValue() > 4);\r\n }\r\n if (this._isCyclic) {\r\n this.closedToNotFound();\r\n stackSmiles = [];\r\n this.dfsSmiles(vertex, stackSmiles, new MutableBoolean(true), new MutableCounter(), [], new MutableCounter(), -1, true);\r\n }\r\n this.closedToFullyClosed();\r\n\r\n stackSmiles = Graph.removeUnnecessaryParentheses(stackSmiles);\r\n let smile = Graph.removeUnnecessaryNumbers(stackSmiles.join(\"\"));\r\n if (smile.length !== 0) {\r\n smiles.push({smiles: smile, isPolyketide: isPolyketide.getValue()});\r\n if (isPolyketide.getValue() === true) {\r\n this._polyketide = true;\r\n }\r\n }\r\n return isPolyketide.getValue();\r\n }\r\n\r\n closedToNotFound() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n }\r\n\r\n closedToFullyClosed() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.FULLY_CLOSED;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * DFS for SMILES\r\n * @param {Vertex} vertex\r\n * @param {Array} stackSmiles output param\r\n * @param {MutableBoolean} isPolyketide\r\n * @param {MutableCounter} cntDecays\r\n * @param {Array} through\r\n * @param {MutableCounter} vertexCounter\r\n * @param lastVertexId last vertex id for setup digits\r\n * @param isSecondPass is second pass of dfs\r\n */\r\n dfsSmiles(vertex, stackSmiles, isPolyketide, cntDecays, through, vertexCounter, lastVertexId = -1, isSecondPass = false) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN && !isSecondPass && lastVertexId !== -1) {\r\n this._isCyclic = true;\r\n if (!vertex.digits.some(e => this.vertices[lastVertexId].digits.includes(e))) {\r\n vertex.digits.push(this._digitCounter);\r\n this.vertices[lastVertexId].digits.push(this._digitCounter);\r\n this._digitCounter++;\r\n }\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n if (vertex.value.element === 'H') {\r\n return;\r\n }\r\n\r\n if (this.first === vertex.id && vertex.value.element === \"C\" && isPolyketide.getValue()) {\r\n stackSmiles.push(\"O\");\r\n isPolyketide.setValue(false);\r\n }\r\n\r\n if (vertex.value.bracket) {\r\n stackSmiles.push(\"[\");\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n if (vertex.value.bracket.hcount > 0) {\r\n stackSmiles.push('H');\r\n if (vertex.value.bracket.hcount > 1) {\r\n stackSmiles.push(vertex.value.bracket.hcount);\r\n }\r\n }\r\n if (vertex.value.bracket.charge > 0) {\r\n stackSmiles.push('+');\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n } else if (vertex.value.bracket.charge < 0) {\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n }\r\n stackSmiles.push(\"]\");\r\n } else {\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n }\r\n vertexCounter.increment();\r\n\r\n if (isSecondPass) {\r\n stackSmiles.push(this.smilesNumbersAdd(vertex));\r\n }\r\n\r\n if (!this._markComponent) {\r\n this._startingVertexes.push(vertex);\r\n }\r\n vertex.component = this._cnt;\r\n this._markComponent = true;\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n if (edge.isDecayAll && lastVertexId !== nextVertex) {\r\n through.push(vertex.value.element);\r\n }\r\n if (edge.isDecay) {\r\n cntDecays.increment();\r\n if (vertex.value.element === \"C\" && vertex.id !== this.first && isPolyketide.getValue()) {\r\n stackSmiles.push(\"(\");\r\n stackSmiles.push(\"O\");\r\n stackSmiles.push(\")\");\r\n isPolyketide.setValue(false);\r\n }\r\n continue;\r\n }\r\n stackSmiles.push(\"(\");\r\n Graph.addBondTypeToStack(edge, stackSmiles);\r\n if (lastVertexId !== nextVertex) {\r\n this.dfsSmiles(this.vertices[nextVertex], stackSmiles, isPolyketide, cntDecays, through, vertexCounter, vertex.id, isSecondPass);\r\n }\r\n Graph.checkStack(stackSmiles);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSmall(vertex, isPolyketide) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n\r\n this._smallGraph.addNeighbour(vertex.component, this.vertices[Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId)].component, Direction.getProperValue(isPolyketide, vertex.value.element, vertex.id, this.first));\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n this.dfsSmall(this.vertices[nextVertex], isPolyketide);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n\r\n static printVertexValue(stackSmiles, vertex) {\r\n if (vertex.value.isPartOfAromaticRing) {\r\n stackSmiles.push(vertex.value.element.toLowerCase());\r\n } else {\r\n stackSmiles.push(vertex.value.element);\r\n }\r\n }\r\n\r\n /**\r\n * Remove numbers which is neighbours in SMILES notation -> need to perform in cyclic structures\r\n * @param {String} smiles SMILES\r\n * @return {String} repaired SMILES\r\n */\r\n static removeUnnecessaryNumbers(smiles) {\r\n if (smiles === null) {\r\n return '';\r\n }\r\n try {\r\n let numbers = this.getNumbers(smiles);\r\n for (let number of numbers) {\r\n let first = this.findFirst(smiles, number);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n let tmpRange = this.removeRangeLast(smiles, first, second, number);\r\n smiles = this.repairSmiles(smiles, tmpRange, first, second, number);\r\n }\r\n return smiles;\r\n } catch (ex) {\r\n return smiles;\r\n }\r\n }\r\n\r\n /**\r\n * Remove unnecessary numbers from SMILES\r\n * @param {String} smiles\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {*}\r\n */\r\n static removeNumbers(smiles, first, second, number) {\r\n if (number > 9) {\r\n let numLength = number.toString().length;\r\n smiles = smiles.slice(0, first - 1) + smiles.slice(first + numLength);\r\n return smiles.slice(0, second - 2 - numLength) + smiles.slice(second - 1);\r\n } else {\r\n smiles = smiles.slice(0, first) + smiles.slice(first + 1);\r\n return smiles.slice(0, second - 1) + smiles.slice(second);\r\n }\r\n }\r\n\r\n /**\r\n * Reapair SMILES\r\n * @param {String} smiles\r\n * @param {String} tmpRange\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {String|*}\r\n */\r\n static repairSmiles(smiles, tmpRange, first, second, number) {\r\n let pattern = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])$\");\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let patternOrg = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])\");\r\n if (patternOrg.test(tmpRange)) {\r\n return smiles;\r\n }\r\n\r\n while (tmpRange.length !== 0) {\r\n if (tmpRange[0] === '(') {\r\n tmpRange = tmpRange.substring(1);\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let leftBrackets = 1;\r\n let rightBrackets = 0;\r\n while (leftBrackets !== rightBrackets) {\r\n switch (tmpRange[0]) {\r\n case '(':\r\n leftBrackets++;\r\n break;\r\n case ')':\r\n rightBrackets++;\r\n break;\r\n }\r\n if (\"\" === tmpRange) {\r\n return smiles;\r\n }\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n return this.repairSmiles(smiles, tmpRange, first, second, number);\r\n } else {\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Substring in range and remove last Organic Subset\r\n * @param smiles\r\n * @param first\r\n * @param second\r\n * @param number\r\n * @return {string}\r\n */\r\n static removeRangeLast(smiles, first, second, number) {\r\n if (number > 9) {\r\n return smiles.substring(first + number.toString().length, second - 1);\r\n } else {\r\n return smiles.substring(first + 1, second);\r\n }\r\n }\r\n\r\n /**\r\n * Get numbers from SMILES\r\n * @param smiles\r\n * @return {Set}\r\n */\r\n static getNumbers(smiles) {\r\n let numbers = new Set();\r\n for (let index = 0; index < smiles.length; ++index) {\r\n if (!isNaN(smiles[index])) {\r\n numbers.add(smiles[index]);\r\n } else if (smiles[index] === '%') {\r\n index++;\r\n let num = \"\";\r\n while (!isNaN(smiles[index])) {\r\n num += smiles[index];\r\n index++;\r\n if (index >= smiles.length) {\r\n break;\r\n }\r\n }\r\n index--;\r\n numbers.add(num);\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * return index of first occurrence number\r\n * @param smiles\r\n * @param number\r\n * @return {number}\r\n */\r\n static findFirst(smiles, number) {\r\n return smiles.indexOf(number);\r\n }\r\n\r\n /**\r\n * return index of first occurrence number from index + 1\r\n * @param smiles\r\n * @param from range no including this point (from, Infinity) = [from + 1, Infinity)\r\n * @param number\r\n * @return {*}\r\n */\r\n static findSecond(smiles, from, number) {\r\n let result = smiles.indexOf(number, from);\r\n if (result === -1) {\r\n throw \"Not Found\";\r\n }\r\n return result;\r\n }\r\n\r\n\r\n smilesNumbersAdd(vertex) {\r\n let numbers = '';\r\n for (let i = 0; i < vertex.digits.length; ++i) {\r\n let num = vertex.digits[i];\r\n if (this._printedDigits.some(e => e === num)) {\r\n let nextVertex = this.vertices.find(e => e.digits.includes(num) && e.id !== vertex.id);\r\n let intersection = vertex.edges.filter(element => nextVertex.edges.includes(element));\r\n\r\n if (intersection.length > 0) {\r\n let bond = this.edges[intersection[0]].bondType;\r\n if (bond !== '-') {\r\n numbers += bond;\r\n }\r\n }\r\n }\r\n\r\n this._printedDigits.push(num);\r\n let numString = num.toString();\r\n if (numString.length === 1) {\r\n numbers += numString;\r\n } else {\r\n numbers += '%' + numString;\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * Return other vertex id then the actual vertex id\r\n * when vertexId === sourceId return targetId\r\n * when vertexId === targetId return sourceId\r\n * @param {Number} vertexId actual vertex id\r\n * @param {Number} sourceId source vertex id\r\n * @param {Number} targetId target vertex id\r\n * @return {Number}\r\n */\r\n static getProperVertex(vertexId, sourceId, targetId) {\r\n if (vertexId === sourceId) return targetId;\r\n else return sourceId;\r\n }\r\n\r\n static repairNumbers(smiles) {\r\n try {\r\n let numbers = Array.from(this.getNumbers(smiles));\r\n numbers.sort(function (a, b) {\r\n return b - a\r\n });\r\n\r\n let index = 1;\r\n for (let number of numbers) {\r\n if (index === number) {\r\n continue;\r\n }\r\n let first = this.findFirst(smiles, number);\r\n if (number > 9) {\r\n smiles = smiles.slice(0, first - 1) + index + smiles.slice(first + number.toString().length);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second - 1) + index + smiles.slice(second + number.toString().length);\r\n } else {\r\n smiles = smiles.slice(0, first) + index + smiles.slice(first + 1);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second) + index + smiles.slice(second + 1);\r\n }\r\n index++;\r\n }\r\n } catch (e) {\r\n return smiles;\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from SMILES\r\n * example CCC(CC)(C) -> CCC(CC)C\r\n * example C(=O)C(C(C)) -> C(=O)CCC\r\n * @param {Array} stackRight\r\n * @return {Array}\r\n */\r\n static removeUnnecessaryParentheses(stackRight) {\r\n if (stackRight.length === 0) return [];\r\n let stackLeft = [], lastLiteral = \"\", literal = \"\";\r\n while (stackRight.length > 0) {\r\n literal = stackRight.shift();\r\n if ((\")\".localeCompare(literal) === 0 && \")\".localeCompare(lastLiteral) === 0)) {\r\n Graph.removeParentheses(stackLeft, false, literal);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n lastLiteral = literal;\r\n }\r\n\r\n literal = stackLeft.pop();\r\n if ((\")\".localeCompare(literal) === 0 && stackRight.length === 0)) {\r\n Graph.removeParentheses(stackLeft);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n return stackLeft;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from stack\r\n * go through stack and when find proper closing bracket,\r\n * then remove it and push back removed data when searching in stack\r\n * @param {Array} stack with unnecessary parentheses to remove\r\n * @param {Boolean} end treat with situation when \")\" is last character of stack -> end = true, else where end = false\r\n * @param {String} literal, when end = false, need to pop from stack and at the end add literal back to stack\r\n */\r\n static removeParentheses(stack, end = true, literal = \"\") {\r\n let stackTmp = [];\r\n let leftBraces = 0, rightBraces = 1;\r\n if (!end) {\r\n stack.pop();\r\n }\r\n while (true) {\r\n let lit = stack.pop();\r\n if (\"(\".localeCompare(lit) === 0) {\r\n leftBraces++;\r\n } else if (\")\".localeCompare(lit) === 0) {\r\n rightBraces++;\r\n }\r\n if (leftBraces === rightBraces) {\r\n Graph.moveAllValuesInStackToAnotherStack(stackTmp, stack);\r\n if (!end) {\r\n stack.push(literal);\r\n }\r\n break;\r\n }\r\n stackTmp.push(lit);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all values from stackSource and push it to stackDestination\r\n * @param {Array} stackSource stack to remove values\r\n * @param {Array} stackDestination stack to add values from stackSource\r\n */\r\n static moveAllValuesInStackToAnotherStack(stackSource, stackDestination) {\r\n while (stackSource.length > 0) {\r\n stackDestination.push(stackSource.pop());\r\n }\r\n }\r\n\r\n /**\r\n * Check last value of stack\r\n * if it one of (, -, = or # then remove all characters in stack to first ( from the end of stack\r\n * elsewhere add ) to stack\r\n * @param {Array} stackSmiles\r\n */\r\n static checkStack(stackSmiles) {\r\n switch (stackSmiles[stackSmiles.length - 1]) {\r\n case \"(\":\r\n case \"-\":\r\n case \"=\":\r\n case \"#\":\r\n Graph.removeAllFromStackToFirstLeftBrace(stackSmiles);\r\n break;\r\n default:\r\n stackSmiles.push(\")\");\r\n }\r\n }\r\n\r\n /**\r\n * Remove all characters from stack to first \"(\"\r\n * @param {Array} stackSmiles\r\n */\r\n static removeAllFromStackToFirstLeftBrace(stackSmiles) {\r\n let literal = stackSmiles.pop();\r\n while (literal !== \"(\") {\r\n if (stackSmiles.length === 0) break;\r\n literal = stackSmiles.pop();\r\n }\r\n }\r\n\r\n /**\r\n * Add bond type to stack\r\n * if edge have = or # bond type add it to stack\r\n * @param {Edge} edge\r\n * @param {Array} stackSmiles\r\n */\r\n static addBondTypeToStack(edge, stackSmiles) {\r\n if (edge.bondType === \"=\" || edge.bondType === \"#\") {\r\n stackSmiles.push(edge.bondType);\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Graph;\r\n","//@ts-check\r\nconst Vector2 = require('./Vector2')\r\n\r\n/** \r\n * A class representing a line.\r\n * \r\n * @property {Vector2} from The Vector2 defining the start of the line.\r\n * @property {Vector2} to The Vector2 defining the end of the line.\r\n * @property {String} elementFrom The element symbol associated with the start of the line.\r\n * @property {String} elementTo The element symbol associated with the end of the line.\r\n * @property {Boolean} chiralFrom A boolean indicating whether or not the source atom is a chiral center.\r\n * @property {Boolean} chiralTo A boolean indicating whether or tno the target atom is a chiral center.\r\n */\r\nclass Line {\r\n /**\r\n * The constructor for the class Line.\r\n *\r\n * @param {Vector2} [from=new Vector2(0, 0)] A vector marking the beginning of the line.\r\n * @param {Vector2} [to=new Vector2(0, 0)] A vector marking the end of the line.\r\n * @param {string} [elementFrom=null] A one-letter representation of the element associated with the vector marking the beginning of the line.\r\n * @param {string} [elementTo=null] A one-letter representation of the element associated with the vector marking the end of the line.\r\n * @param {Boolean} [chiralFrom=false] Whether or not the from atom is a chiral center.\r\n * @param {Boolean} [chiralTo=false] Whether or not the to atom is a chiral center.\r\n * @param {Boolean} [isDecayPoint=false] Whether or not the edge is a decay point\r\n */\r\n constructor(from = new Vector2(0,0), to = new Vector2(0, 0), elementFrom = null, elementTo = null, chiralFrom = false, chiralTo = false, isDecayPoint = false) {\r\n this.from = from;\r\n this.to = to;\r\n this.elementFrom = elementFrom;\r\n this.elementTo = elementTo;\r\n this.chiralFrom = chiralFrom;\r\n this.chiralTo = chiralTo;\r\n this.isDecayPoint = isDecayPoint;\r\n }\r\n\r\n /**\r\n * Clones this line and returns the clone.\r\n *\r\n * @returns {Line} A clone of this line.\r\n */\r\n clone() {\r\n return new Line(this.from.clone(), this.to.clone(), this.elementFrom, this.elementTo);\r\n }\r\n\r\n /**\r\n * Returns the length of this line.\r\n *\r\n * @returns {Number} The length of this line.\r\n */\r\n getLength() {\r\n return Math.sqrt(Math.pow(this.to.x - this.from.x, 2) + \r\n Math.pow(this.to.y - this.from.y, 2));\r\n }\r\n\r\n\r\n /**\r\n * Returns the angle of the line in relation to the coordinate system (the x-axis).\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n // Get the angle between the line and the x-axis\r\n let diff = Vector2.subtract(this.getRightVector(), this.getLeftVector());\r\n return diff.angle();\r\n }\r\n\r\n /**\r\n * Returns the right vector (the vector with the larger x value).\r\n *\r\n * @returns {Vector2} The right vector.\r\n */\r\n getRightVector() {\r\n // Return the vector with the larger x value (the right one)\r\n if (this.from.x < this.to.x) {\r\n return this.to;\r\n } else {\r\n return this.from;\r\n }\r\n }\r\n \r\n /**\r\n * Returns the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {Vector2} The left vector.\r\n */\r\n getLeftVector() {\r\n // Return the vector with the smaller x value (the left one)\r\n if (this.from.x < this.to.x) {\r\n return this.from;\r\n } else {\r\n return this.to;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the right vector (the vector with the larger x value).\r\n *\r\n * @returns {String} The element associated with the right vector.\r\n */\r\n getRightElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementTo;\r\n } else {\r\n return this.elementFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {String} The element associated with the left vector.\r\n */\r\n getLeftElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementFrom;\r\n } else {\r\n return this.elementTo;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the right vector (the vector with the larger x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the right vector is a chiral center.\r\n */\r\n getRightChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralTo;\r\n } else {\r\n return this.chiralFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the left vector (the vector with the smaller x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the left vector is a chiral center.\r\n */\r\n getLeftChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralFrom;\r\n } else {\r\n return this.chiralTo;\r\n }\r\n }\r\n\r\n /**\r\n * Set the value of the right vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setRightVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.to.x = x;\r\n this.to.y = y;\r\n } else {\r\n this.from.x = x;\r\n this.from.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Set the value of the left vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setLeftVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.from.x = x;\r\n this.from.y = y;\r\n } else {\r\n this.to.x = x;\r\n this.to.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this line to be aligned with the x-axis. The center of rotation is the left vector.\r\n *\r\n * @returns {Line} This line.\r\n */\r\n rotateToXAxis() {\r\n let left = this.getLeftVector();\r\n \r\n this.setRightVector(left.x + this.getLength(), left.y);\r\n \r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate the line by a given value (in radians). The center of rotation is the left vector.\r\n *\r\n * @param {Number} theta The angle (in radians) to rotate the line.\r\n * @returns {Line} This line.\r\n */\r\n rotate(theta) {\r\n let l = this.getLeftVector();\r\n let r = this.getRightVector();\r\n let sinTheta = Math.sin(theta);\r\n let cosTheta = Math.cos(theta);\r\n\r\n let x = cosTheta * (r.x - l.x) - sinTheta * (r.y - l.y) + l.x;\r\n let y = sinTheta * (r.x - l.x) - cosTheta * (r.y - l.y) + l.y;\r\n \r\n this.setRightVector(x, y);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"from\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenFrom(by) {\r\n let f = Vector2.subtract(this.to, this.from);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.from.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"to\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenTo(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.to.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shorten the right side.\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenRight(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenTo(by);\r\n } else {\r\n this.shortenFrom(by);\r\n }\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Shorten the left side.\r\n * \r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenLeft(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenFrom(by);\r\n } else {\r\n this.shortenTo(by);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from both directions by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shorten(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by / 2.0);\r\n \r\n this.to.add(f);\r\n this.from.subtract(f);\r\n\r\n return this;\r\n }\r\n}\r\n\r\nmodule.exports = Line;","/** \r\n * A static class containing helper functions for math-related tasks. \r\n */\r\nclass MathHelper {\r\n /**\r\n * Rounds a value to a given number of decimals.\r\n *\r\n * @static\r\n * @param {Number} value A number.\r\n * @param {Number} decimals The number of decimals.\r\n * @returns {Number} A number rounded to a given number of decimals.\r\n */\r\n static round(value, decimals) {\r\n decimals = decimals ? decimals : 1;\r\n return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);\r\n }\r\n\r\n /**\r\n * Returns the means of the angles contained in an array. In radians.\r\n *\r\n * @static\r\n * @param {Number[]} arr An array containing angles (in radians).\r\n * @returns {Number} The mean angle in radians.\r\n */\r\n static meanAngle(arr) {\r\n let sin = 0.0;\r\n let cos = 0.0;\r\n \r\n for (var i = 0; i < arr.length; i++) {\r\n sin += Math.sin(arr[i]);\r\n cos += Math.cos(arr[i]);\r\n }\r\n\r\n return Math.atan2(sin / arr.length, cos / arr.length);\r\n }\r\n\r\n /**\r\n * Returns the inner angle of a n-sided regular polygon.\r\n *\r\n * @static\r\n * @param {Number} n Number of sides of a regular polygon.\r\n * @returns {Number} The inner angle of a given regular polygon.\r\n */\r\n static innerAngle(n) {\r\n return MathHelper.toRad((n - 2) * 180 / n);\r\n }\r\n\r\n /**\r\n * Returns the circumradius of a n-sided regular polygon with a given side-length.\r\n *\r\n * @static\r\n * @param {Number} s The side length of the regular polygon.\r\n * @param {Number} n The number of sides.\r\n * @returns {Number} The circumradius of the regular polygon.\r\n */\r\n static polyCircumradius(s, n) {\r\n return s / (2 * Math.sin(Math.PI / n));\r\n }\r\n\r\n /**\r\n * Returns the apothem of a regular n-sided polygon based on its radius.\r\n *\r\n * @static\r\n * @param {Number} r The radius.\r\n * @param {Number} n The number of edges of the regular polygon.\r\n * @returns {Number} The apothem of a n-sided polygon based on its radius.\r\n */\r\n static apothem(r, n) {\r\n return r * Math.cos(Math.PI / n);\r\n }\r\n\r\n static apothemFromSideLength(s, n) {\r\n let r = MathHelper.polyCircumradius(s, n);\r\n \r\n return MathHelper.apothem(r, n);\r\n }\r\n\r\n /**\r\n * The central angle of a n-sided regular polygon. In radians.\r\n *\r\n * @static\r\n * @param {Number} n The number of sides of the regular polygon.\r\n * @returns {Number} The central angle of the n-sided polygon in radians.\r\n */\r\n static centralAngle(n) {\r\n return MathHelper.toRad(360 / n);\r\n }\r\n\r\n /**\r\n * Convertes radians to degrees.\r\n *\r\n * @static\r\n * @param {Number} rad An angle in radians.\r\n * @returns {Number} The angle in degrees.\r\n */\r\n static toDeg(rad) {\r\n return rad * MathHelper.degFactor;\r\n }\r\n\r\n /**\r\n * Converts degrees to radians.\r\n *\r\n * @static\r\n * @param {Number} deg An angle in degrees.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static toRad(deg) {\r\n return deg * MathHelper.radFactor;\r\n }\r\n\r\n /**\r\n * Returns the parity of the permutation (1 or -1)\r\n * @param {(Array|Uint8Array)} arr An array containing the permutation.\r\n * @returns {Number} The parity of the permutation (1 or -1), where 1 means even and -1 means odd.\r\n */\r\n static parityOfPermutation(arr) {\r\n let visited = new Uint8Array(arr.length);\r\n let evenLengthCycleCount = 0;\r\n\r\n let traverseCycle = function(i, cycleLength = 0) {\r\n if (visited[i] === 1) {\r\n return cycleLength;\r\n }\r\n\r\n cycleLength++;\r\n\r\n visited[i] = 1;\r\n return traverseCycle(arr[i], cycleLength);\r\n }\r\n\r\n for (var i = 0; i < arr.length; i++) {\r\n if (visited[i] === 1) {\r\n continue;\r\n }\r\n\r\n let cycleLength = traverseCycle(i);\r\n evenLengthCycleCount += (1 - cycleLength % 2);\r\n }\r\n\r\n return evenLengthCycleCount % 2 ? -1 : 1;\r\n }\r\n\r\n /** The factor to convert degrees to radians. */\r\n static get radFactor() {\r\n return Math.PI / 180.0;\r\n }\r\n\r\n /** The factor to convert radians to degrees. */\r\n static get degFactor() {\r\n return 180.0 / Math.PI;\r\n }\r\n\r\n /** Two times PI. */\r\n static get twoPI() {\r\n return 2.0 * Math.PI;\r\n }\r\n}\r\n\r\nmodule.exports = MathHelper;","/**\r\n *@property {boolean} value is boolean\r\n */\r\nclass MutableBoolean {\r\n\r\n /**\r\n * @param {boolean} value\r\n */\r\n constructor(value) {\r\n this.value = value;\r\n }\r\n\r\n setValue(value) {\r\n this.value = value;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableBoolean;\r\n","/**\r\n * @param {Number} value\r\n */\r\nclass MutableCounter {\r\n\r\n constructor() {\r\n this.value = 0;\r\n }\r\n\r\n increment() {\r\n this.value++;\r\n }\r\n\r\n reset() {\r\n this.value = 0;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableCounter;\r\n","\r\nclass Neighbour {\r\n\r\n constructor(neighbour, direction) {\r\n this.neighbour = neighbour;\r\n this.direction = direction;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Neighbour;\r\n","//@ts-check\r\nconst VertexState = require(\"./VertexState\");\r\n\r\nclass Node {\r\n\r\n constructor(id) {\r\n this.id = id;\r\n this.neighbours = [];\r\n this.onRing = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n\r\n addNeighbour(neighbour) {\r\n this.neighbours.push(neighbour);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Node;\r\n","// WHEN REPLACING, CHECK FOR:\r\n// KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\nmodule.exports = (function () {\r\n \"use strict\";\r\n\r\n /*\r\n * Generated by PEG.js 0.10.0.\r\n *\r\n * http://pegjs.org/\r\n */\r\n\r\n function peg$subclass(child, parent) {\r\n function ctor() {\r\n this.constructor = child;\r\n }\r\n ctor.prototype = parent.prototype;\r\n child.prototype = new ctor();\r\n }\r\n\r\n function peg$SyntaxError(message, expected, found, location) {\r\n this.message = message;\r\n this.expected = expected;\r\n this.found = found;\r\n this.location = location;\r\n this.name = \"SyntaxError\";\r\n\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(this, peg$SyntaxError);\r\n }\r\n }\r\n\r\n peg$subclass(peg$SyntaxError, Error);\r\n\r\n peg$SyntaxError.buildMessage = function (expected, found) {\r\n var DESCRIBE_EXPECTATION_FNS = {\r\n literal: function (expectation) {\r\n return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";\r\n },\r\n\r\n \"class\": function (expectation) {\r\n var escapedParts = \"\",\r\n i;\r\n\r\n for (i = 0; i < expectation.parts.length; i++) {\r\n escapedParts += expectation.parts[i] instanceof Array ?\r\n classEscape(expectation.parts[i][0]) + \"-\" + classEscape(expectation.parts[i][1]) :\r\n classEscape(expectation.parts[i]);\r\n }\r\n\r\n return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";\r\n },\r\n\r\n any: function (expectation) {\r\n return \"any character\";\r\n },\r\n\r\n end: function (expectation) {\r\n return \"end of input\";\r\n },\r\n\r\n other: function (expectation) {\r\n return expectation.description;\r\n }\r\n };\r\n\r\n function hex(ch) {\r\n return ch.charCodeAt(0).toString(16).toUpperCase();\r\n }\r\n\r\n function literalEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function classEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\\]/g, '\\\\]')\r\n .replace(/\\^/g, '\\\\^')\r\n .replace(/-/g, '\\\\-')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function describeExpectation(expectation) {\r\n return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\r\n }\r\n\r\n function describeExpected(expected) {\r\n var descriptions = new Array(expected.length),\r\n i, j;\r\n\r\n for (i = 0; i < expected.length; i++) {\r\n descriptions[i] = describeExpectation(expected[i]);\r\n }\r\n\r\n descriptions.sort();\r\n\r\n if (descriptions.length > 0) {\r\n for (i = 1, j = 1; i < descriptions.length; i++) {\r\n if (descriptions[i - 1] !== descriptions[i]) {\r\n descriptions[j] = descriptions[i];\r\n j++;\r\n }\r\n }\r\n descriptions.length = j;\r\n }\r\n\r\n switch (descriptions.length) {\r\n case 1:\r\n return descriptions[0];\r\n\r\n case 2:\r\n return descriptions[0] + \" or \" + descriptions[1];\r\n\r\n default:\r\n return descriptions.slice(0, -1).join(\", \") +\r\n \", or \" +\r\n descriptions[descriptions.length - 1];\r\n }\r\n }\r\n\r\n function describeFound(found) {\r\n return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";\r\n }\r\n\r\n return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\r\n };\r\n\r\n function peg$parse(input, options) {\r\n options = options !== void 0 ? options : {};\r\n\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n var nOpenParentheses = input.split('(').length - 1;\r\n var nCloseParentheses = input.split(')').length - 1;\r\n\r\n if (nOpenParentheses !== nCloseParentheses) {\r\n throw peg$buildSimpleError('The number of opening parentheses does not match the number of closing parentheses.', 0);\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n var peg$FAILED = {},\r\n\r\n peg$startRuleFunctions = {\r\n chain: peg$parsechain\r\n },\r\n peg$startRuleFunction = peg$parsechain,\r\n\r\n peg$c0 = function (s) {\r\n var branches = [];\r\n var rings = [];\r\n\r\n for (var i = 0; i < s[1].length; i++) {\r\n branches.push(s[1][i]);\r\n }\r\n\r\n\r\n for (var i = 0; i < s[2].length; i++) {\r\n var bond = (s[2][i][0]) ? s[2][i][0] : '-';\r\n rings.push({\r\n 'bond': bond,\r\n 'id': s[2][i][1]\r\n });\r\n }\r\n\r\n for (var i = 0; i < s[3].length; i++) {\r\n branches.push(s[3][i]);\r\n }\r\n\r\n for (var i = 0; i < s[6].length; i++) {\r\n branches.push(s[6][i]);\r\n }\r\n\r\n return {\r\n 'atom': s[0],\r\n 'isBracket': s[0].element ? true : false,\r\n 'branches': branches,\r\n 'branchCount': branches.length,\r\n 'ringbonds': rings,\r\n 'ringbondCount': rings.length,\r\n 'bond': s[4] ? s[4] : '-',\r\n 'next': s[5],\r\n 'hasNext': s[5] ? true : false\r\n }\r\n\r\n return s;\r\n },\r\n peg$c1 = \"(\",\r\n peg$c2 = peg$literalExpectation(\"(\", false),\r\n peg$c3 = \")\",\r\n peg$c4 = peg$literalExpectation(\")\", false),\r\n peg$c5 = function (b) {\r\n var bond = (b[1]) ? b[1] : '-';\r\n b[2].branchBond = bond;\r\n return b[2]\r\n },\r\n peg$c6 = function (a) {\r\n return a;\r\n },\r\n peg$c7 = /^[\\-=#$:\\/\\\\.]/,\r\n peg$c8 = peg$classExpectation([\"-\", \"=\", \"#\", \"$\", \":\", \"/\", \"\\\\\", \".\"], false, false),\r\n peg$c9 = function (b) {\r\n return b;\r\n },\r\n peg$c10 = \"[\",\r\n peg$c11 = peg$literalExpectation(\"[\", false),\r\n peg$c12 = \"se\",\r\n peg$c13 = peg$literalExpectation(\"se\", false),\r\n peg$c14 = \"as\",\r\n peg$c15 = peg$literalExpectation(\"as\", false),\r\n peg$c16 = \"]\",\r\n peg$c17 = peg$literalExpectation(\"]\", false),\r\n peg$c18 = function (b) {\r\n return {\r\n 'isotope': b[1],\r\n 'element': b[2],\r\n 'chirality': b[3],\r\n 'hcount': b[4],\r\n 'charge': b[5],\r\n 'class': b[6]\r\n }\r\n },\r\n peg$c19 = \"B\",\r\n peg$c20 = peg$literalExpectation(\"B\", false),\r\n peg$c21 = \"r\",\r\n peg$c22 = peg$literalExpectation(\"r\", false),\r\n peg$c23 = \"C\",\r\n peg$c24 = peg$literalExpectation(\"C\", false),\r\n peg$c25 = \"l\",\r\n peg$c26 = peg$literalExpectation(\"l\", false),\r\n peg$c27 = /^[NOPSFI]/,\r\n peg$c28 = peg$classExpectation([\"N\", \"O\", \"P\", \"S\", \"F\", \"I\"], false, false),\r\n peg$c29 = function (o) {\r\n if (o.length > 1) return o.join('');\r\n return o;\r\n },\r\n peg$c30 = /^[bcnops]/,\r\n peg$c31 = peg$classExpectation([\"b\", \"c\", \"n\", \"o\", \"p\", \"s\"], false, false),\r\n peg$c32 = \"*\",\r\n peg$c33 = peg$literalExpectation(\"*\", false),\r\n peg$c34 = function (w) {\r\n return w;\r\n },\r\n peg$c35 = /^[A-Z]/,\r\n peg$c36 = peg$classExpectation([\r\n [\"A\", \"Z\"]\r\n ], false, false),\r\n peg$c37 = /^[a-z]/,\r\n peg$c38 = peg$classExpectation([\r\n [\"a\", \"z\"]\r\n ], false, false),\r\n peg$c39 = function (e) {\r\n return e.join('');\r\n },\r\n peg$c40 = \"%\",\r\n peg$c41 = peg$literalExpectation(\"%\", false),\r\n peg$c42 = /^[1-9]/,\r\n peg$c43 = peg$classExpectation([\r\n [\"1\", \"9\"]\r\n ], false, false),\r\n peg$c44 = /^[0-9]/,\r\n peg$c45 = peg$classExpectation([\r\n [\"0\", \"9\"]\r\n ], false, false),\r\n peg$c46 = function (r) {\r\n if (r.length == 1) return Number(r);\r\n return Number(r.join('').replace('%', ''));\r\n },\r\n peg$c47 = \"@\",\r\n peg$c48 = peg$literalExpectation(\"@\", false),\r\n peg$c49 = \"TH\",\r\n peg$c50 = peg$literalExpectation(\"TH\", false),\r\n peg$c51 = /^[12]/,\r\n peg$c52 = peg$classExpectation([\"1\", \"2\"], false, false),\r\n peg$c53 = \"AL\",\r\n peg$c54 = peg$literalExpectation(\"AL\", false),\r\n peg$c55 = \"SP\",\r\n peg$c56 = peg$literalExpectation(\"SP\", false),\r\n peg$c57 = /^[1-3]/,\r\n peg$c58 = peg$classExpectation([\r\n [\"1\", \"3\"]\r\n ], false, false),\r\n peg$c59 = \"TB\",\r\n peg$c60 = peg$literalExpectation(\"TB\", false),\r\n peg$c61 = \"OH\",\r\n peg$c62 = peg$literalExpectation(\"OH\", false),\r\n peg$c63 = function (c) {\r\n if (!c[1]) return '@';\r\n if (c[1] == '@') return '@@';\r\n\r\n return c[1].join('').replace(',', '');\r\n },\r\n peg$c64 = function (c) {\r\n return c;\r\n },\r\n peg$c65 = \"+\",\r\n peg$c66 = peg$literalExpectation(\"+\", false),\r\n peg$c67 = function (c) {\r\n if (!c[1]) return 1;\r\n if (c[1] != '+') return Number(c[1].join(''));\r\n return 2;\r\n },\r\n peg$c68 = \"-\",\r\n peg$c69 = peg$literalExpectation(\"-\", false),\r\n peg$c70 = function (c) {\r\n if (!c[1]) return -1;\r\n if (c[1] != '-') return -Number(c[1].join(''));\r\n return -2;\r\n },\r\n peg$c71 = \"H\",\r\n peg$c72 = peg$literalExpectation(\"H\", false),\r\n peg$c73 = function (h) {\r\n if (h[1]) return Number(h[1]);\r\n return 1;\r\n },\r\n peg$c74 = \":\",\r\n peg$c75 = peg$literalExpectation(\":\", false),\r\n peg$c76 = /^[0]/,\r\n peg$c77 = peg$classExpectation([\"0\"], false, false),\r\n peg$c78 = function (c) {\r\n return Number(c[1][0] + c[1][1].join(''));\r\n },\r\n peg$c79 = function (i) {\r\n return Number(i.join(''));\r\n },\r\n\r\n peg$currPos = 0,\r\n peg$savedPos = 0,\r\n peg$posDetailsCache = [{\r\n line: 1,\r\n column: 1\r\n }],\r\n peg$maxFailPos = 0,\r\n peg$maxFailExpected = [],\r\n peg$silentFails = 0,\r\n\r\n peg$result;\r\n\r\n if (\"startRule\" in options) {\r\n if (!(options.startRule in peg$startRuleFunctions)) {\r\n throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");\r\n }\r\n\r\n peg$startRuleFunction = peg$startRuleFunctions[options.startRule];\r\n }\r\n\r\n function text() {\r\n return input.substring(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function location() {\r\n return peg$computeLocation(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function expected(description, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildStructuredError(\r\n [peg$otherExpectation(description)],\r\n input.substring(peg$savedPos, peg$currPos),\r\n location\r\n );\r\n }\r\n\r\n function error(message, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildSimpleError(message, location);\r\n }\r\n\r\n function peg$literalExpectation(text, ignoreCase) {\r\n return {\r\n type: \"literal\",\r\n text: text,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$classExpectation(parts, inverted, ignoreCase) {\r\n return {\r\n type: \"class\",\r\n parts: parts,\r\n inverted: inverted,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$anyExpectation() {\r\n return {\r\n type: \"any\"\r\n };\r\n }\r\n\r\n function peg$endExpectation() {\r\n return {\r\n type: \"end\"\r\n };\r\n }\r\n\r\n function peg$otherExpectation(description) {\r\n return {\r\n type: \"other\",\r\n description: description\r\n };\r\n }\r\n\r\n function peg$computePosDetails(pos) {\r\n var details = peg$posDetailsCache[pos],\r\n p;\r\n\r\n if (details) {\r\n return details;\r\n } else {\r\n p = pos - 1;\r\n while (!peg$posDetailsCache[p]) {\r\n p--;\r\n }\r\n\r\n details = peg$posDetailsCache[p];\r\n details = {\r\n line: details.line,\r\n column: details.column\r\n };\r\n\r\n while (p < pos) {\r\n if (input.charCodeAt(p) === 10) {\r\n details.line++;\r\n details.column = 1;\r\n } else {\r\n details.column++;\r\n }\r\n\r\n p++;\r\n }\r\n\r\n peg$posDetailsCache[pos] = details;\r\n return details;\r\n }\r\n }\r\n\r\n function peg$computeLocation(startPos, endPos) {\r\n var startPosDetails = peg$computePosDetails(startPos),\r\n endPosDetails = peg$computePosDetails(endPos);\r\n\r\n return {\r\n start: {\r\n offset: startPos,\r\n line: startPosDetails.line,\r\n column: startPosDetails.column\r\n },\r\n end: {\r\n offset: endPos,\r\n line: endPosDetails.line,\r\n column: endPosDetails.column\r\n }\r\n };\r\n }\r\n\r\n function peg$fail(expected) {\r\n if (peg$currPos < peg$maxFailPos) {\r\n return;\r\n }\r\n\r\n if (peg$currPos > peg$maxFailPos) {\r\n peg$maxFailPos = peg$currPos;\r\n peg$maxFailExpected = [];\r\n }\r\n\r\n peg$maxFailExpected.push(expected);\r\n }\r\n\r\n function peg$buildSimpleError(message, location) {\r\n return new peg$SyntaxError(message, null, null, location);\r\n }\r\n\r\n function peg$buildStructuredError(expected, found, location) {\r\n return new peg$SyntaxError(\r\n peg$SyntaxError.buildMessage(expected, found),\r\n expected,\r\n found,\r\n location\r\n );\r\n }\r\n\r\n function peg$parsechain() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n s2 = peg$parseatom();\r\n if (s2 !== peg$FAILED) {\r\n s3 = [];\r\n s4 = peg$parsebranch();\r\n while (s4 !== peg$FAILED) {\r\n s3.push(s4);\r\n s4 = peg$parsebranch();\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = [];\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n while (s5 !== peg$FAILED) {\r\n s4.push(s5);\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n s6 = peg$parsebranch();\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n s6 = peg$parsebranch();\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsechain();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = [];\r\n s9 = peg$parsebranch();\r\n while (s9 !== peg$FAILED) {\r\n s8.push(s9);\r\n s9 = peg$parsebranch();\r\n }\r\n if (s8 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c0(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebranch() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 40) {\r\n s2 = peg$c1;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c2);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parsebond();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = peg$parsechain();\r\n if (s4 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 41) {\r\n s5 = peg$c3;\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c4);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c5(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseatom() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseorganicsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsearomaticsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsebracketatom();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebond() {\r\n var s0, s1;\r\n s0 = peg$currPos;\r\n if (peg$c7.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n\r\n // Hack to resolve problem caused by:\r\n // O=C(N[C@@H](CC(O)=O)C(N[C@H](C1=CC=C(O)C=C1)C(N[C@@H](CC(O)=O)C(NCC(N[C@@H](C(N[C@@H]([C@H](C)CC(O)=O)C(N/C(C(O[C@H](C)[C@@H]2NC([C@H](CO)NC(C(O3)C3CCC)=O)=O)=O)=C\\\\\\\\C4=CNC5=C4C=CC=C5)=O)=O)[C@H](O)C(N)=O)=O)=O)=O)=O)[C@H](CC(O)=O)NC([C@@H](CC6=CNC7=C6C=CC=C7)NC2=O)=O\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n if (s1 === input.charAt(peg$currPos + 1)) {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n throw peg$buildSimpleError('The parser encountered a bond repetition.', peg$currPos + 1);\r\n }\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c8);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c9(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebracketatom() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 91) {\r\n s2 = peg$c10;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c11);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parseisotope();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c12) {\r\n s4 = peg$c12;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c13);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c14) {\r\n s4 = peg$c14;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c15);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsearomaticsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parseelementsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = peg$parsechiral();\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsehcount();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsecharge();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = peg$parseclass();\r\n if (s8 === peg$FAILED) {\r\n s8 = null;\r\n }\r\n if (s8 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 93) {\r\n s9 = peg$c16;\r\n peg$currPos++;\r\n } else {\r\n s9 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c17);\r\n }\r\n }\r\n if (s9 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8, s9];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c18(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseorganicsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 66) {\r\n s2 = peg$c19;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c20);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 114) {\r\n s3 = peg$c21;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c22);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 67) {\r\n s2 = peg$c23;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c24);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 108) {\r\n s3 = peg$c25;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c26);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c27.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c28);\r\n }\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c29(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsearomaticsymbol() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (peg$c30.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c31);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsewildcard() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 42) {\r\n s1 = peg$c32;\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c33);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c34(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseelementsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c35.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c36);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c37.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c38);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c39(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsering() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 37) {\r\n s2 = peg$c40;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c41);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c46(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsechiral() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s2 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s3 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c49) {\r\n s4 = peg$c49;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c50);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c53) {\r\n s4 = peg$c53;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c54);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c55) {\r\n s4 = peg$c55;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c56);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c57.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c58);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c59) {\r\n s4 = peg$c59;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c60);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c61) {\r\n s4 = peg$c61;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c62);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c63(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsecharge() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseposcharge();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsenegcharge();\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c64(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseposcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s2 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s3 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c67(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsenegcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s2 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s3 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c70(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsehcount() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 72) {\r\n s2 = peg$c71;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c72);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c73(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseclass() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 58) {\r\n s2 = peg$c74;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c75);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n if (peg$c76.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c77);\r\n }\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c78(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseisotope() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = null;\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c79(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n peg$result = peg$startRuleFunction();\r\n\r\n if (peg$result !== peg$FAILED && peg$currPos === input.length) {\r\n return peg$result;\r\n } else {\r\n if (peg$result !== peg$FAILED && peg$currPos < input.length) {\r\n peg$fail(peg$endExpectation());\r\n }\r\n\r\n throw peg$buildStructuredError(\r\n peg$maxFailExpected,\r\n peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,\r\n peg$maxFailPos < input.length ?\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) :\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n SyntaxError: peg$SyntaxError,\r\n parse: peg$parse\r\n };\r\n})();","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Vertex = require('./Vertex')\r\nconst RingConnection = require('./RingConnection')\r\n\r\n/** \r\n * A class representing a ring.\r\n * \r\n * @property {Number} id The id of this ring.\r\n * @property {Number[]} members An array containing the vertex ids of the ring members.\r\n * @property {Number[]} edges An array containing the edge ids of the edges between the ring members.\r\n * @property {Number[]} insiders An array containing the vertex ids of the vertices contained within the ring if it is a bridged ring.\r\n * @property {Number[]} neighbours An array containing the ids of neighbouring rings.\r\n * @property {Boolean} positioned A boolean indicating whether or not this ring has been positioned.\r\n * @property {Vector2} center The center of this ring.\r\n * @property {Ring[]} rings The rings contained within this ring if this ring is bridged.\r\n * @property {Boolean} isBridged A boolean whether or not this ring is bridged.\r\n * @property {Boolean} isPartOfBridged A boolean whether or not this ring is part of a bridge ring.\r\n * @property {Boolean} isSpiro A boolean whether or not this ring is part of a spiro.\r\n * @property {Boolean} isFused A boolean whether or not this ring is part of a fused ring.\r\n * @property {Number} centralAngle The central angle of this ring.\r\n * @property {Boolean} canFlip A boolean indicating whether or not this ring allows flipping of attached vertices to the inside of the ring.\r\n */\r\nclass Ring {\r\n /**\r\n * The constructor for the class Ring.\r\n *\r\n * @param {Number[]} members An array containing the vertex ids of the members of the ring to be created.\r\n */\r\n constructor(members) {\r\n this.id = null;\r\n this.members = members;\r\n this.edges = [];\r\n this.insiders = [];\r\n this.neighbours = [];\r\n this.positioned = false;\r\n this.center = new Vector2(0, 0);\r\n this.rings = [];\r\n this.isBridged = false;\r\n this.isPartOfBridged = false;\r\n this.isSpiro = false;\r\n this.isFused = false;\r\n this.centralAngle = 0.0;\r\n this.canFlip = true;\r\n }\r\n \r\n /**\r\n * Clones this ring and returns the clone.\r\n *\r\n * @returns {Ring} A clone of this ring.\r\n */\r\n clone() {\r\n let clone = new Ring(this.members);\r\n\r\n clone.id = this.id;\r\n clone.insiders = ArrayHelper.clone(this.insiders);\r\n clone.neighbours = ArrayHelper.clone(this.neighbours);\r\n clone.positioned = this.positioned;\r\n clone.center = this.center.clone();\r\n clone.rings = ArrayHelper.clone(this.rings);\r\n clone.isBridged = this.isBridged;\r\n clone.isPartOfBridged = this.isPartOfBridged;\r\n clone.isSpiro = this.isSpiro;\r\n clone.isFused = this.isFused;\r\n clone.centralAngle = this.centralAngle;\r\n clone.canFlip = this.canFlip;\r\n\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns the size (number of members) of this ring.\r\n *\r\n * @returns {Number} The size (number of members) of this ring.\r\n */\r\n getSize() {\r\n return this.members.length;\r\n }\r\n\r\n /**\r\n * Gets the polygon representation (an array of the ring-members positional vectors) of this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices representing the current molecule.\r\n * @returns {Vector2[]} An array of the positional vectors of the ring members.\r\n */\r\n getPolygon(vertices) {\r\n let polygon = [];\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n polygon.push(vertices[this.members[i]].position);\r\n }\r\n\r\n return polygon;\r\n }\r\n\r\n /**\r\n * Returns the angle of this ring in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n return Math.PI - this.centralAngle;\r\n }\r\n\r\n /**\r\n * Loops over the members of this ring from a given start position in a direction opposite to the vertex id passed as the previousId.\r\n *\r\n * @param {Vertex[]} vertices The vertices associated with the current molecule.\r\n * @param {Function} callback A callback with the current vertex id as a parameter.\r\n * @param {Number} startVertexId The vertex id of the start vertex.\r\n * @param {Number} previousVertexId The vertex id of the previous vertex (the loop calling the callback function will run in the opposite direction of this vertex).\r\n */\r\n eachMember(vertices, callback, startVertexId, previousVertexId) {\r\n startVertexId = startVertexId || startVertexId === 0 ? startVertexId : this.members[0];\r\n let current = startVertexId;\r\n let max = 0;\r\n\r\n while (current != null && max < 100) {\r\n let prev = current;\r\n \r\n callback(prev);\r\n current = vertices[current].getNextInRing(vertices, this.id, previousVertexId);\r\n previousVertexId = prev;\r\n \r\n // Stop while loop when arriving back at the start vertex\r\n if (current == startVertexId) {\r\n current = null;\r\n }\r\n\r\n max++;\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array containing the neighbouring rings of this ring ordered by ring size.\r\n *\r\n * @param {RingConnection[]} ringConnections An array of ring connections associated with the current molecule.\r\n * @returns {Object[]} An array of neighbouring rings sorted by ring size. Example: { n: 5, neighbour: 1 }.\r\n */\r\n getOrderedNeighbours(ringConnections) {\r\n let orderedNeighbours = Array(this.neighbours.length);\r\n \r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n let vertices = RingConnection.getVertices(ringConnections, this.id, this.neighbours[i]);\r\n \r\n orderedNeighbours[i] = {\r\n n: vertices.length,\r\n neighbour: this.neighbours[i]\r\n };\r\n }\r\n\r\n orderedNeighbours.sort(function (a, b) {\r\n // Sort highest to lowest\r\n return b.n - a.n;\r\n });\r\n\r\n return orderedNeighbours;\r\n }\r\n\r\n /**\r\n * Check whether this ring is an implicitly defined benzene-like (e.g. C1=CC=CC=C1) with 6 members and 3 double bonds.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring is an implicitly defined benzene-like.\r\n */\r\n isBenzeneLike(vertices) {\r\n let db = this.getDoubleBondCount(vertices);\r\n let length = this.members.length;\r\n\r\n return db === 3 && length === 6 ||\r\n db === 2 && length === 5 ;\r\n }\r\n\r\n /**\r\n * Get the number of double bonds inside this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Number} The number of double bonds inside this ring.\r\n */\r\n getDoubleBondCount(vertices) {\r\n let doubleBondCount = 0;\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n let atom = vertices[this.members[i]].value;\r\n\r\n if (atom.bondType === '=' || atom.branchBond === '=') {\r\n doubleBondCount++;\r\n }\r\n }\r\n\r\n return doubleBondCount;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring contains a member with a given vertex id.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not this ring contains a member with the given vertex id.\r\n */\r\n contains(vertexId) {\r\n for (let i = 0; i < this.members.length; i++) {\r\n if (this.members[i] == vertexId) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n\r\nmodule.exports = Ring;","//@ts-check\r\nconst Vertex = require('./Vertex')\r\nconst Ring = require('./Ring')\r\n\r\n/** \r\n * A class representing a ring connection.\r\n * \r\n * @property {Number} id The id of this ring connection.\r\n * @property {Number} firstRingId A ring id.\r\n * @property {Number} secondRingId A ring id.\r\n * @property {Set} vertices A set containing the vertex ids participating in the ring connection.\r\n */\r\nclass RingConnection {\r\n /**\r\n * The constructor for the class RingConnection.\r\n *\r\n * @param {Ring} firstRing A ring.\r\n * @param {Ring} secondRing A ring.\r\n */\r\n constructor(firstRing, secondRing) {\r\n this.id = null;\r\n this.firstRingId = firstRing.id;\r\n this.secondRingId = secondRing.id;\r\n this.vertices = new Set();\r\n\r\n for (var m = 0; m < firstRing.members.length; m++) {\r\n let c = firstRing.members[m];\r\n\r\n for (let n = 0; n < secondRing.members.length; n++) {\r\n let d = secondRing.members[n];\r\n\r\n if (c === d) {\r\n this.addVertex(c);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adding a vertex to the ring connection.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n */\r\n addVertex(vertexId) {\r\n this.vertices.add(vertexId);\r\n }\r\n\r\n /**\r\n * Update the ring id of this ring connection that is not the ring id supplied as the second argument.\r\n *\r\n * @param {Number} ringId A ring id. The new ring id to be set.\r\n * @param {Number} otherRingId A ring id. The id that is NOT to be updated.\r\n */\r\n updateOther(ringId, otherRingId) {\r\n if (this.firstRingId === otherRingId) {\r\n this.secondRingId = ringId;\r\n } else {\r\n this.firstRingId = ringId;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.\r\n * \r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.\r\n */\r\n containsRing(ringId) {\r\n return this.firstRingId === ringId || this.secondRingId === ringId;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring connection is a bridge in a bridged ring.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.\r\n */\r\n isBridge(vertices) {\r\n if (this.vertices.size > 2) {\r\n return true;\r\n }\r\n\r\n for (let vertexId of this.vertices) {\r\n if(vertices[vertexId].value.rings.length > 2) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two rings are connected by a bridged bond.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.\r\n */\r\n static isBridge(ringConnections, vertices, firstRingId, secondRingId) {\r\n let ringConnection = null;\r\n \r\n for (let i = 0; i < ringConnections.length; i++) {\r\n ringConnection = ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return ringConnection.isBridge(vertices);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Retruns the neighbouring rings of a given ring.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array of ring ids of neighbouring rings.\r\n */\r\n static getNeighbours(ringConnections, ringId) {\r\n let neighbours = [];\r\n\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n \r\n if (ringConnection.firstRingId === ringId) {\r\n neighbours.push(ringConnection.secondRingId);\r\n } else if (ringConnection.secondRingId === ringId) {\r\n neighbours.push(ringConnection.firstRingId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Returns an array of vertex ids associated with a given ring connection.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Number[]} An array of vertex ids associated with the ring connection.\r\n */\r\n static getVertices(ringConnections, firstRingId, secondRingId) {\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return [...ringConnection.vertices];\r\n }\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = RingConnection","//@ts-check\r\nconst Graph = require('./Graph')\r\n\r\n/** A class encapsulating the functionality to find the smallest set of smallest rings in a graph. */\r\nclass SSSR {\r\n /**\r\n * Returns an array containing arrays, each representing a ring from the smallest set of smallest rings in the graph.\r\n * \r\n * @param {Graph} graph A Graph object.\r\n * @param {Boolean} [experimental=false] Whether or not to use experimental SSSR.\r\n * @returns {Array[]} An array containing arrays, each representing a ring from the smallest set of smallest rings in the group.\r\n */\r\n static getRings(graph, experimental=false) {\r\n let adjacencyMatrix = graph.getComponentsAdjacencyMatrix();\r\n if (adjacencyMatrix.length === 0) {\r\n return null;\r\n }\r\n\r\n let connectedComponents = Graph.getConnectedComponents(adjacencyMatrix);\r\n let rings = Array();\r\n\r\n for (var i = 0; i < connectedComponents.length; i++) {\r\n let connectedComponent = connectedComponents[i];\r\n let ccAdjacencyMatrix = graph.getSubgraphAdjacencyMatrix([...connectedComponent]);\r\n\r\n let arrBondCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n let arrRingCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n arrRingCount[j] = 0;\r\n arrBondCount[j] = 0;\r\n\r\n for (var k = 0; k < ccAdjacencyMatrix[j].length; k++) {\r\n arrBondCount[j] += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n // Get the edge number and the theoretical number of rings in SSSR\r\n let nEdges = 0;\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n for (var k = j + 1; k < ccAdjacencyMatrix.length; k++) {\r\n nEdges += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n let nSssr = nEdges - ccAdjacencyMatrix.length + 1;\r\n\r\n // console.log(nEdges, ccAdjacencyMatrix.length, nSssr);\r\n // console.log(SSSR.getEdgeList(ccAdjacencyMatrix));\r\n // console.log(ccAdjacencyMatrix);\r\n\r\n // If all vertices have 3 incident edges, calculate with different formula (see Euler)\r\n let allThree = true;\r\n for (var j = 0; j < arrBondCount.length; j++) {\r\n if (arrBondCount[j] !== 3) {\r\n allThree = false;\r\n }\r\n }\r\n\r\n if (allThree) {\r\n nSssr = 2.0 + nEdges - ccAdjacencyMatrix.length;\r\n }\r\n\r\n // All vertices are part of one ring if theres only one ring.\r\n if (nSssr === 1) {\r\n rings.push([...connectedComponent]);\r\n continue;\r\n }\r\n \r\n if (experimental) {\r\n nSssr = 999;\r\n }\r\n\r\n let { d, pe, pe_prime } = SSSR.getPathIncludedDistanceMatrices(ccAdjacencyMatrix);\r\n let c = SSSR.getRingCandidates(d, pe, pe_prime);\r\n let sssr = SSSR.getSSSR(c, d, ccAdjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nSssr);\r\n\r\n for (var j = 0; j < sssr.length; j++) {\r\n let ring = Array(sssr[j].size);\r\n let index = 0;\r\n\r\n for (let val of sssr[j]) {\r\n // Get the original id of the vertex back\r\n ring[index++] = connectedComponent[val];\r\n }\r\n\r\n rings.push(ring);\r\n }\r\n }\r\n \r\n\r\n // So, for some reason, this would return three rings for C1CCCC2CC1CCCC2, which is wrong\r\n // As I don't have time to fix this properly, it will stay in. I'm sorry next person who works\r\n // on it. At that point it might be best to reimplement the whole SSSR thing...\r\n return rings;\r\n }\r\n\r\n /**\r\n * Creates a printable string from a matrix (2D array).\r\n * \r\n * @param {Array[]} matrix A 2D array.\r\n * @returns {String} A string representing the matrix.\r\n */\r\n static matrixToString(matrix) {\r\n let str = '';\r\n\r\n for (var i = 0; i < matrix.length; i++) {\r\n for (var j = 0; j < matrix[i].length; j++) {\r\n str += matrix[i][j] + ' ';\r\n }\r\n\r\n str += '\\n';\r\n }\r\n\r\n return str;\r\n }\r\n\r\n /**\r\n * Returnes the two path-included distance matrices used to find the sssr.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Object} The path-included distance matrices. { p1, p2 }\r\n */\r\n static getPathIncludedDistanceMatrices(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let d = Array(length);\r\n let pe = Array(length);\r\n let pe_prime = Array(length);\r\n var l = 0;\r\n var m = 0;\r\n var n = 0;\r\n\r\n var i = length;\r\n while (i--) {\r\n d[i] = Array(length);\r\n pe[i] = Array(length);\r\n pe_prime[i] = Array(length);\r\n\r\n var j = length;\r\n while (j--) {\r\n d[i][j] = (i === j || adjacencyMatrix[i][j] === 1) ? adjacencyMatrix[i][j] : Number.POSITIVE_INFINITY;\r\n\r\n if (d[i][j] === 1) {\r\n pe[i][j] = [[[i, j]]];\r\n } else {\r\n pe[i][j] = Array();\r\n }\r\n\r\n pe_prime[i][j] = Array();\r\n }\r\n }\r\n\r\n var k = length;\r\n var j;\r\n while (k--) {\r\n i = length;\r\n while (i--) {\r\n j = length;\r\n while (j--) {\r\n const previousPathLength = d[i][j];\r\n const newPathLength = d[i][k] + d[k][j];\r\n\r\n if (previousPathLength > newPathLength) {\r\n var l, m, n;\r\n if (previousPathLength === newPathLength + 1) {\r\n pe_prime[i][j] = [pe[i][j].length];\r\n l = pe[i][j].length\r\n while (l--) {\r\n pe_prime[i][j][l] = [pe[i][j][l].length];\r\n m = pe[i][j][l].length\r\n while (m--) {\r\n pe_prime[i][j][l][m] = [pe[i][j][l][m].length];\r\n n = pe[i][j][l][m].length;\r\n while (n--) {\r\n pe_prime[i][j][l][m][n] = [pe[i][j][l][m][0], pe[i][j][l][m][1]];\r\n }\r\n }\r\n }\r\n } else {\r\n pe_prime[i][j] = Array();\r\n }\r\n\r\n d[i][j] = newPathLength;\r\n\r\n pe[i][j] = [[]];\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[k][j][0][l]);\r\n }\r\n } else if (previousPathLength === newPathLength) {\r\n if (pe[i][k].length && pe[k][j].length) {\r\n var l;\r\n if (pe[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j][0] = tmp\r\n }\r\n }\r\n } else if (previousPathLength === newPathLength - 1) {\r\n var l;\r\n if (pe_prime[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j][0] = tmp;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n d: d,\r\n pe: pe,\r\n pe_prime: pe_prime\r\n };\r\n }\r\n\r\n /**\r\n * Get the ring candidates from the path-included distance matrices.\r\n * \r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @returns {Array[]} The ring candidates.\r\n */\r\n static getRingCandidates(d, pe, pe_prime) {\r\n let length = d.length;\r\n let candidates = Array();\r\n let c = 0;\r\n\r\n for (let i = 0; i < length; i++) {\r\n for (let j = 0; j < length; j++) {\r\n if (d[i][j] === 0 || (pe[i][j].length === 1 && pe_prime[i][j] === 0)) {\r\n continue;\r\n } else {\r\n // c is the number of vertices in the cycle.\r\n if (pe_prime[i][j].length !== 0) {\r\n c = 2 * (d[i][j] + 0.5);\r\n } else {\r\n c = 2 * d[i][j];\r\n }\r\n\r\n if (c !== Infinity) {\r\n candidates.push([c, pe[i][j], pe_prime[i][j]]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Candidates have to be sorted by c\r\n candidates.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n\r\n return candidates;\r\n }\r\n\r\n /**\r\n * Searches the candidates for the smallest set of smallest rings.\r\n * \r\n * @param {Array[]} c The candidates.\r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @param {Number} nsssr The theoretical number of rings in the graph.\r\n * @returns {Set[]} The smallest set of smallest rings.\r\n */\r\n static getSSSR(c, d, adjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nsssr) {\r\n let cSssr = Array();\r\n let allBonds = Array();\r\n\r\n for (let i = 0; i < c.length; i++) {\r\n if (c[i][0] % 2 !== 0) {\r\n for (let j = 0; j < c[i][2].length; j++) {\r\n let bonds = c[i][1][0].concat(c[i][2][j]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n } else {\r\n for (let j = 0; j < c[i][1].length - 1; j++) {\r\n let bonds = c[i][1][j].concat(c[i][1][j + 1]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return cSssr;\r\n }\r\n\r\n /**\r\n * Returns the number of edges in a graph defined by an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of edges in the graph defined by the adjacency matrix.\r\n */\r\n static getEdgeCount(adjacencyMatrix) {\r\n let edgeCount = 0;\r\n let length = adjacencyMatrix.length;\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeCount++;\r\n }\r\n }\r\n }\r\n\r\n return edgeCount;\r\n }\r\n\r\n /**\r\n * Returns an edge list constructed form an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Array[]} An edge list. E.g. [ [ 0, 1 ], ..., [ 16, 2 ] ]\r\n */\r\n static getEdgeList(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let edgeList = Array();\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeList.push([i, j]);\r\n }\r\n }\r\n }\r\n\r\n return edgeList;\r\n }\r\n\r\n /**\r\n * Return a set of vertex indices contained in an array of bonds.\r\n * \r\n * @param {Array} bonds An array of bonds. A bond is defined as [ sourceVertexId, targetVertexId ].\r\n * @returns {Set} An array of vertices.\r\n */\r\n static bondsToAtoms(bonds) {\r\n let atoms = new Set();\r\n\r\n var i = bonds.length;\r\n while (i--) {\r\n atoms.add(bonds[i][0]);\r\n atoms.add(bonds[i][1]);\r\n }\r\n return atoms;\r\n }\r\n\r\n /**\r\n * Returns the number of bonds within a set of atoms.\r\n * \r\n * @param {Set} atoms An array of atom ids.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of bonds in a set of atoms.\r\n */\r\n static getBondCount(atoms, adjacencyMatrix) {\r\n let count = 0;\r\n for (let u of atoms) {\r\n for (let v of atoms) {\r\n if (u === v) {\r\n continue;\r\n }\r\n count += adjacencyMatrix[u][v]\r\n }\r\n }\r\n\r\n return count / 2;\r\n }\r\n\r\n /**\r\n * Checks whether or not a given path already exists in an array of paths.\r\n * \r\n * @param {Set[]} pathSets An array of sets each representing a path.\r\n * @param {Set} pathSet A set representing a path.\r\n * @param {Array[]} bonds The bonds associated with the current path.\r\n * @param {Array[]} allBonds All bonds currently associated with rings in the SSSR set.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @returns {Boolean} A boolean indicating whether or not a give path is contained within a set.\r\n */\r\n static pathSetsContain(pathSets, pathSet, bonds, allBonds, arrBondCount, arrRingCount) {\r\n var i = pathSets.length;\r\n while (i--) {\r\n if (SSSR.isSupersetOf(pathSet, pathSets[i])) {\r\n return true;\r\n }\r\n\r\n if (pathSets[i].size !== pathSet.size) {\r\n continue;\r\n }\r\n\r\n if (SSSR.areSetsEqual(pathSets[i], pathSet)) {\r\n return true;\r\n }\r\n }\r\n\r\n // Check if the edges from the candidate are already all contained within the paths of the set of paths.\r\n // TODO: For some reason, this does not replace the isSupersetOf method above -> why?\r\n let count = 0;\r\n let allContained = false;\r\n i = bonds.length;\r\n while (i--) {\r\n var j = allBonds.length;\r\n while (j--) {\r\n if (bonds[i][0] === allBonds[j][0] && bonds[i][1] === allBonds[j][1] ||\r\n bonds[i][1] === allBonds[j][0] && bonds[i][0] === allBonds[j][1]) {\r\n count++;\r\n }\r\n\r\n if (count === bonds.length) {\r\n allContained = true;\r\n }\r\n }\r\n }\r\n\r\n // If all the bonds and thus vertices are already contained within other rings\r\n // check if there's one vertex with ringCount < bondCount\r\n let specialCase = false;\r\n if (allContained) {\r\n for (let element of pathSet) {\r\n if (arrRingCount[element] < arrBondCount[element]) {\r\n specialCase = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (allContained && !specialCase) {\r\n return true;\r\n }\r\n\r\n // Update the ring counts for the vertices\r\n for (let element of pathSet) {\r\n arrRingCount[element]++;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two sets are equal (contain the same elements).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not the two sets are equal.\r\n */\r\n static areSetsEqual(setA, setB) {\r\n if (setA.size !== setB.size) {\r\n return false;\r\n }\r\n\r\n for (let element of setA) {\r\n if (!setB.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Checks whether or not a set (setA) is a superset of another set (setB).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not setB is a superset of setA.\r\n */\r\n static isSupersetOf(setA, setB) {\r\n for (var element of setB) {\r\n if (!setA.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\nmodule.exports = SSSR;","//@ts-check\r\n\r\nclass SequenceType {\r\n\r\n static get VALUES() {\r\n return {\r\n LINEAR: \"linear\",\r\n CYCLIC: \"cyclic\",\r\n BRANCH: \"branched\",\r\n BRANCH_CYCLIC: \"branch-cyclic\",\r\n LINEAR_POLYKETIDE: \"linear-polyketide\",\r\n CYCLIC_POLYKETIDE: \"cyclic-polyketide\",\r\n OTHER: \"other\",\r\n }\r\n }\r\n\r\n static getTypeFromValues(isCyclic, isBranch, isOther) {\r\n if (isOther) { return this.VALUES.OTHER;}\r\n if (!isCyclic && !isBranch) {\r\n return this.VALUES.LINEAR;\r\n } else if(isCyclic && !isBranch) {\r\n return this.VALUES.CYCLIC;\r\n } else if (!isCyclic) {\r\n return this.VALUES.BRANCH;\r\n } else {\r\n return this.VALUES.BRANCH_CYCLIC;\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = SequenceType;\r\n","//@ts-check\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst VertexState = require('./VertexState');\r\nconst Neighbour = require('./Neighbour');\r\nconst Direction = require('./Direction');\r\n\r\nclass SmallGraph {\r\n\r\n constructor() {\r\n this._nodes = [];\r\n this.isOther = false;\r\n this._branch = false;\r\n this.isCyclic = false;\r\n this.isBranched = false;\r\n this.sequenceType = SequenceType.VALUES.LINEAR;\r\n this._nodeOnRing = null;\r\n }\r\n\r\n addVertex(node) {\r\n this._nodes.push(node);\r\n }\r\n\r\n addNeighbour(nodeId, neighbour, direction) {\r\n this._nodes[nodeId].addNeighbour(new Neighbour(neighbour, direction));\r\n }\r\n\r\n dfsInitialization() {\r\n this._nodes.forEach(e => e.vertexState = VertexState.VALUES.NOT_FOUND);\r\n }\r\n\r\n getSourceNode() {\r\n let ends = [];\r\n for (let index = 0; index < this._nodes.length; ++index) {\r\n if (this._nodes[index].neighbours.length === 1) {\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.C) {\r\n return this._nodes[index];\r\n }\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.POLYKETIDE) {\r\n return this._nodes[index];\r\n }\r\n ends.push(this._nodes[index]);\r\n }\r\n }\r\n if (ends.length > 0) {\r\n return ends[0];\r\n }\r\n return null;\r\n }\r\n\r\n oneCyclic() {\r\n if (this._nodes.length === 0) {\r\n return false;\r\n }\r\n this.dfsInitialization();\r\n this.isCyclic = false;\r\n if (this._nodes.length === 2 && this._nodes[0].neighbours.length === 2 && this._nodes[1].neighbours.length === 2) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = this._nodes[0];\r\n } else {\r\n this.dfsCyclic(this._nodes[0], -1);\r\n }\r\n }\r\n\r\n dfsCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = vertex;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.neighbours.length; ++i) {\r\n if (vertexFromId !== vertex.neighbours[i].neighbour) {\r\n this.dfsCyclic(this._nodes[vertex.neighbours[i].neighbour], vertex.id);\r\n }\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSequenceStart() {\r\n if (this._nodes.length === 0) {\r\n return;\r\n }\r\n this.dfsInitialization();\r\n this.sequence = \"\";\r\n if (this.isCyclic) {\r\n this.findRing(this._nodeOnRing);\r\n this.dfsSequenceCyclic(this._nodeOnRing);\r\n } else {\r\n let sourceNode = this.getSourceNode();\r\n if (sourceNode !== null) {\r\n this.dfsSequence(this.getSourceNode(), -1);\r\n } else {\r\n this.sequenceType = 'other';\r\n this.isOther = true;\r\n return;\r\n }\r\n }\r\n if (this.sequence.charAt(this.sequence.length - 1) === '-') {\r\n this.sequence = this.sequence.substr(0, this.sequence.length - 1);\r\n }\r\n this.sequenceType = SequenceType.getTypeFromValues(this.isCyclic, this.isBranched, this.isOther);\r\n }\r\n\r\n arrayContainsTimes(array, searchValue, times) {\r\n let cnt = 0;\r\n for (let index = 0; index < array.length; ++index) {\r\n if (array[index].neighbour === searchValue) {\r\n cnt++;\r\n if (cnt === times) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n findRing(start) {\r\n let queue = [];\r\n let firstPath = [start.id];\r\n let firstPass = true;\r\n queue.push(firstPath);\r\n while (queue.length !== 0) {\r\n let path = queue.pop();\r\n let last = path[path.length - 1];\r\n let node = this._nodes[last];\r\n if (node.id === start.id && !firstPass) {\r\n if (path.length === 3 && path[0] === path[2] && !this.arrayContainsTimes(this._nodes[path[0]].neighbours, path[1], 2)) {\r\n continue;\r\n }\r\n path.forEach(v => this._nodes[v].onRing = true);\r\n continue;\r\n }\r\n node.neighbours.forEach(\r\n neighbour => {\r\n if (!path.some(e => e === neighbour.neighbour) || neighbour.neighbour === start.id) {\r\n let newPath = [...path];\r\n newPath.push(neighbour.neighbour);\r\n queue.push(newPath);\r\n }\r\n }\r\n );\r\n firstPass = false;\r\n }\r\n }\r\n\r\n sortByRingPreference(array) {\r\n let sortedArray = [...array];\r\n sortedArray.sort((a, b) => {\r\n if (this._nodes[a.neighbour].onRing === this._nodes[b.neighbour].onRing) {\r\n if (a.direction > b.direction) {\r\n return -1;\r\n } else if (a.direction < b.direction) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n } else if (this._nodes[a.neighbour].onRing) {\r\n return 1;\r\n } else {\r\n return -1;\r\n }\r\n });\r\n return sortedArray;\r\n }\r\n\r\n dfsSequenceCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n let sortedNeighbours = this.sortByRingPreference(vertex.neighbours);\r\n for (let index = 0; index < sortedNeighbours.length; ++index) {\r\n if (vertexFromId === sortedNeighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequenceCyclic(this._nodes[sortedNeighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n printVertex(vertexId) {\r\n this.sequence += `[${vertexId}]`;\r\n }\r\n\r\n printDash() {\r\n if (']' === this.sequence[this.sequence.length - 1]) {\r\n this.sequence += '-';\r\n }\r\n }\r\n\r\n printLeftBrace(vertex) {\r\n if (vertex.neighbours.length > 2) {\r\n if (this.isBranched) {\r\n this.isOther = true;\r\n }\r\n this.sequence += '\\\\(';\r\n this._branch = true;\r\n this.isBranched = true;\r\n }\r\n }\r\n\r\n printRightBrace() {\r\n if (this._branch) {\r\n this.sequence += '\\\\)';\r\n this._branch = false;\r\n }\r\n }\r\n\r\n dfsSequence(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n for (let index = 0; index < vertex.neighbours.length; ++index) {\r\n if (vertexFromId === vertex.neighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequence(this._nodes[vertex.neighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n}\r\n\r\nmodule.exports = SmallGraph;\r\n","// we use the drawer to do all the preprocessing. then we take over the drawing\r\n// portion to output to svg\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Atom = require('./Atom');\r\nconst Drawer = require('./Drawer');\r\nconst Graph = require('./Graph');\r\nconst Line = require('./Line');\r\nconst SvgWrapper = require('./SvgWrapper');\r\nconst ThemeManager = require('./ThemeManager');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgDrawer {\r\n constructor(options) {\r\n this.preprocessor = new Drawer(options);\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to an svg element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML svg element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n\r\n * @returns {Oject} The dimensions of the drawing in { width, height }\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n let preprocessor = this.preprocessor;\r\n\r\n preprocessor.initDraw(data, themeName, infoOnly);\r\n\r\n if (!infoOnly) {\r\n this.themeManager = new ThemeManager(this.preprocessor.opts.themes, themeName);\r\n this.svgWrapper = new SvgWrapper(this.themeManager, target, this.preprocessor.opts);\r\n }\r\n\r\n preprocessor.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.svgWrapper.determineDimensions(preprocessor.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(preprocessor.opts.debug);\r\n this.drawVertices(preprocessor.opts.debug);\r\n\r\n if (preprocessor.opts.debug) {\r\n console.log(preprocessor.graph);\r\n console.log(preprocessor.rings);\r\n console.log(preprocessor.ringConnections);\r\n }\r\n\r\n return this.svgWrapper.constructSvg();\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let preprocessor = this.preprocessor,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n drawn = Array(this.preprocessor.graph.edges.length);\r\n\r\n drawn.fill(false);\r\n\r\n graph.traverseBF(0, vertex => {\r\n let edges = graph.getEdges(vertex.id);\r\n for (var i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n this.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let ring = rings[i];\r\n\r\n if (preprocessor.isRingAromatic(ring)) {\r\n this.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bond.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n svgWrapper = this.svgWrapper,\r\n edge = preprocessor.graph.edges[edgeId],\r\n vertexA = preprocessor.graph.vertices[edge.sourceId],\r\n vertexB = preprocessor.graph.vertices[edge.targetId],\r\n elementA = vertexA.value.element,\r\n elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && preprocessor.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position,\r\n b = vertexB.position,\r\n normals = preprocessor.getEdgeNormals(edge),\r\n // Create a point on each side of the line\r\n sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || preprocessor.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && preprocessor.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = preprocessor.areVerticesInSameRing(vertexA, vertexB);\r\n let s = preprocessor.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(opts.bondSpacing);\r\n normals[1].multiplyScalar(opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line = null;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n }\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n // preprocessor.canvasWrapper.drawLine(line, true);\r\n svgWrapper.drawLine(line, true);\r\n } else {\r\n // preprocessor.canvasWrapper.drawLine(line);\r\n svgWrapper.drawLine(line);\r\n }\r\n\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((edge.center || vertexA.isTerminal() && vertexB.isTerminal()) ||\r\n (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1)) {\r\n this.multiplyNormals(normals, opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB),\r\n lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n } else if ((s.sideCount[0] > s.sideCount[1]) ||\r\n (s.totalSideCount[0] > s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((s.sideCount[0] < s.sideCount[1]) ||\r\n (s.totalSideCount[0] <= s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n svgWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else if (edge.wedge === 'down') {\r\n svgWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else {\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n svgWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n svgWrapper = this.svgWrapper;\r\n\r\n var i = graph.vertices.length;\r\n for (var i = 0; i < graph.vertices.length; i++) {\r\n let vertex = graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(graph.vertices);\r\n let isTerminal = opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (opts.atomVisualization === 'allballs') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || graph.vertices.length === 1) {\r\n if (opts.atomVisualization === 'default') {\r\n svgWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (opts.atomVisualization === 'balls') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = graph.vertices[vertex.neighbours[0]].position;\r\n let b = graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n svgWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (opts.debug) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let center = rings[i].center;\r\n svgWrapper.drawDebugPoint(center.x, center.y, 'r: ' + rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.preprocessor.getTotalOverlapScore();\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n return this.preprocessor.getMolecularFormula();\r\n }\r\n\r\n /**\r\n * @param {Array} normals list of normals to multiply\r\n * @param {Number} spacing value to multiply normals by\r\n */\r\n multiplyNormals(normals, spacing) {\r\n normals[0].multiplyScalar(spacing);\r\n normals[1].multiplyScalar(spacing);\r\n }\r\n}\r\n\r\nmodule.exports = SvgDrawer;","const {\r\n getChargeText\r\n} = require('./UtilityFunctions');\r\n\r\nconst Line = require('./Line');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgWrapper {\r\n constructor(themeManager, target, options) {\r\n this.svg = document.getElementById(target);\r\n this.opts = options;\r\n this.gradientId = 0;\r\n\r\n // maintain a list of line elements and their corresponding gradients\r\n // maintain a list of vertex elements\r\n this.paths = [];\r\n this.vertices = [];\r\n this.gradients = [];\r\n\r\n // maintain the offset for drawing purposes\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n // maintain the dimensions\r\n this.drawingWidth = 0;\r\n this.drawingHeight = 0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // for managing color schemes\r\n this.themeManager = themeManager;\r\n\r\n // create the mask\r\n this.maskElements = [];\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\r\n mask.setAttributeNS(null, 'x', 0);\r\n mask.setAttributeNS(null, 'y', 0);\r\n mask.setAttributeNS(null, 'width', '100%');\r\n mask.setAttributeNS(null, 'height', '100%');\r\n mask.setAttributeNS(null, 'fill', 'white');\r\n\r\n this.maskElements.push(mask);\r\n\r\n // clear the svg element\r\n while (this.svg.firstChild) {\r\n this.svg.removeChild(this.svg.firstChild);\r\n }\r\n }\r\n\r\n constructSvg() {\r\n // TODO: add the defs element to put gradients in\r\n let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'),\r\n masks = document.createElementNS('http://www.w3.org/2000/svg', 'mask'),\r\n style = document.createElementNS('http://www.w3.org/2000/svg', 'style'),\r\n paths = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n vertices = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n pathChildNodes = this.paths;\r\n\r\n // give the mask an id\r\n masks.setAttributeNS(null, 'id', 'text-mask');\r\n\r\n // create the css styles\r\n style.appendChild(document.createTextNode(`\r\n .element {\r\n font: ${this.opts.fontSizeLarge}pt Helvetica, Arial, sans-serif;\r\n alignment-baseline: 'middle';\r\n }\r\n .sub {\r\n font: ${this.opts.fontSizeSmall}pt Helvetica, Arial, sans-serif;\r\n }\r\n `));\r\n\r\n for (let path of pathChildNodes) {\r\n paths.appendChild(path);\r\n }\r\n for (let vertex of this.vertices) {\r\n vertices.appendChild(vertex);\r\n }\r\n for (let mask of this.maskElements) {\r\n masks.appendChild(mask);\r\n }\r\n for (let gradient of this.gradients) {\r\n defs.appendChild(gradient);\r\n }\r\n\r\n paths.setAttributeNS(null, 'mask', 'url(#text-mask)');\r\n\r\n if (this.svg) {\r\n this.svg.appendChild(defs);\r\n this.svg.appendChild(masks);\r\n this.svg.appendChild(style);\r\n this.svg.appendChild(paths);\r\n this.svg.appendChild(vertices);\r\n return this.svg;\r\n } else {\r\n let container = document.createElementNS('http://www.w3.org/2000/svg', 'g');\r\n container.appendChild(defs);\r\n container.appendChild(masks);\r\n container.appendChild(style);\r\n container.appendChild(paths);\r\n container.appendChild(vertices);\r\n return container;\r\n }\r\n }\r\n\r\n /**\r\n * Create a linear gradient to apply to a line\r\n *\r\n * @param {Line} line the line to apply the gradiation to.\r\n */\r\n createGradient(line) {\r\n // create the gradient and add it\r\n let gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient'),\r\n gradientUrl = `line-${this.gradientId++}`,\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n gradient.setAttributeNS(null, 'id', gradientUrl);\r\n gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\r\n gradient.setAttributeNS(null, 'x1', fromX);\r\n gradient.setAttributeNS(null, 'y1', fromY);\r\n gradient.setAttributeNS(null, 'x2', toX);\r\n gradient.setAttributeNS(null, 'y2', toY);\r\n\r\n let firstStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n firstStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getLeftElement()) || this.themeManager.getColor('C'));\r\n firstStop.setAttributeNS(null, 'offset', '20%');\r\n\r\n let secondStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n secondStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getRightElement() || this.themeManager.getColor('C')));\r\n secondStop.setAttributeNS(null, 'offset', '100%');\r\n\r\n gradient.appendChild(firstStop);\r\n gradient.appendChild(secondStop);\r\n\r\n this.gradients.push(gradient);\r\n\r\n return gradientUrl;\r\n }\r\n\r\n /**\r\n * Create a tspan element for sub or super scripts that styles the text\r\n * appropriately as one of those text types.\r\n *\r\n * @param {String} text the actual text\r\n * @param {String} shift the type of text, either 'sub', or 'super'\r\n */\r\n createSubSuperScripts(text, shift) {\r\n let elem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n elem.setAttributeNS(null, 'baseline-shift', shift);\r\n elem.appendChild(document.createTextNode(text));\r\n elem.setAttributeNS(null, 'class', 'sub');\r\n\r\n return elem;\r\n }\r\n\r\n /**\r\n * Determine drawing dimensiosn based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n determineDimensions(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n let padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n let scaleX = this.svg.clientWidth / this.drawingWidth;\r\n let scaleY = this.svg.clientHeight / this.drawingHeight;\r\n\r\n let scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n let viewBoxDim = Math.round(this.drawingWidth > this.drawingHeight ? this.drawingWidth : this.drawingHeight);\r\n\r\n this.svg.setAttributeNS(null, 'viewBox', `0 0 ${viewBoxDim} ${viewBoxDim}`);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.svg.clientHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.svg.clientWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Draw an svg ellipse as a ball.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n ball.setAttributeNS(null, 'cx', x + this.offsetX);\r\n ball.setAttributeNS(null, 'cy', y + this.offsetY);\r\n ball.setAttributeNS(null, 'r', this.opts.bondLength / 4.5);\r\n ball.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n\r\n this.vertices.push(ball);\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone(),\r\n normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral(),\r\n start,\r\n end;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n } else {\r\n start = l;\r\n end = r;\r\n }\r\n\r\n let dir = Vector2.subtract(end, start).normalize(),\r\n length = line.getLength(),\r\n step = 1.25 / (length / (this.opts.bondThickness * 3.0)),\r\n changed = false;\r\n\r\n let gradient = this.createGradient(line);\r\n\r\n for (let t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length),\r\n startDash = Vector2.add(start, to),\r\n width = 1.5 * t,\r\n dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n startDash.subtract(dashOffset);\r\n let endDash = startDash.clone();\r\n endDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n\r\n this.drawLine(new Line(startDash, endDash), null, gradient);\r\n }\r\n }\r\n\r\n /**\r\n * Draws a debug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + this.offsetX);\r\n point.setAttributeNS(null, 'cy', y + this.offsetY);\r\n point.setAttributeNS(null, 'r', '2');\r\n point.setAttributeNS(null, 'fill', '#f00');\r\n this.vertices.push(point);\r\n this.drawDebugText(x, y, debugText);\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\r\n textElem.setAttributeNS(null, 'x', x + this.offsetX);\r\n textElem.setAttributeNS(null, 'y', y + this.offsetY);\r\n textElem.setAttributeNS(null, 'class', 'debug');\r\n textElem.setAttributeNS(null, 'fill', '#ff0000');\r\n textElem.setAttributeNS(null, 'style', `\r\n font: 5px Droid Sans, sans-serif;\r\n `);\r\n textElem.appendChild(document.createTextNode(text));\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * Draws a line.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} dashed defaults to false.\r\n * @param {String} gradient gradient url. Defaults to null.\r\n */\r\n drawLine(line, dashed = false, gradient = null) {\r\n let opts = this.opts,\r\n stylesArr = [\r\n ['stroke-linecap', 'round'],\r\n ['stroke-dasharray', dashed ? '5, 5' : 'none'],\r\n ],\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n let styles = stylesArr.map(sub => sub.join(':')).join(';'),\r\n lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line');\r\n\r\n lineElem.setAttributeNS(null, 'x1', fromX);\r\n lineElem.setAttributeNS(null, 'y1', fromY);\r\n lineElem.setAttributeNS(null, 'x2', toX);\r\n lineElem.setAttributeNS(null, 'y2', toY);\r\n lineElem.setAttributeNS(null, 'style', styles);\r\n this.paths.push(lineElem);\r\n\r\n if (gradient == null) {\r\n gradient = this.createGradient(line, fromX, fromY, toX, toY);\r\n }\r\n lineElem.setAttributeNS(null, 'stroke', `url('#${gradient}')`);\r\n }\r\n\r\n /**\r\n * Draw a point.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // first create a mask\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', x + offsetX);\r\n mask.setAttributeNS(null, 'cy', y + offsetY);\r\n mask.setAttributeNS(null, 'r', '1.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // now create the point\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + offsetX);\r\n point.setAttributeNS(null, 'cy', y + offsetY);\r\n point.setAttributeNS(null, 'r', '0.75');\r\n point.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n this.vertices.push(point);\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n pos = {\r\n x: x + offsetX,\r\n y: y + offsetY,\r\n },\r\n textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text'),\r\n writingMode = 'horizontal-tb',\r\n letterSpacing = 'normal',\r\n textOrientation = 'mixed',\r\n textDirection = 'direction: ltr;',\r\n xShift = -2,\r\n yShift = 2.5;\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', pos.x);\r\n mask.setAttributeNS(null, 'cy', pos.y);\r\n mask.setAttributeNS(null, 'r', '3.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // determine writing mode\r\n if (/up|down/.test(direction) && !isTerminal) {\r\n writingMode = 'vertical-rl';\r\n textOrientation = 'upright';\r\n letterSpacing = '-1px';\r\n }\r\n\r\n if (direction === 'down' && !isTerminal) {\r\n xShift = 0;\r\n yShift = -2;\r\n } else if (direction === 'up' && !isTerminal) {\r\n xShift = 0.5;\r\n } else if (direction === 'left') {\r\n xShift = 2;\r\n }\r\n\r\n if (direction === 'left' || (direction === 'up' && !isTerminal)) {\r\n textDirection = 'direction: rtl; unicode-bidi: bidi-override;'\r\n }\r\n\r\n // now the text element\r\n textElem.setAttributeNS(null, 'x', pos.x + xShift);\r\n textElem.setAttributeNS(null, 'y', pos.y + yShift);\r\n textElem.setAttributeNS(null, 'class', 'element');\r\n textElem.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n textElem.setAttributeNS(null, 'style', `\r\n text-anchor: start;\r\n writing-mode: ${writingMode};\r\n text-orientation: ${textOrientation};\r\n letter-spacing: ${letterSpacing};\r\n ${textDirection}\r\n `);\r\n\r\n let textNode = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n // special case for element names that are 2 letters\r\n if (elementName.length > 1) {\r\n let textAnchor = /up|down/.test(direction) ? 'middle' : 'start';\r\n\r\n textNode.setAttributeNS(null, 'style', `\r\n unicode-bidi: plaintext;\r\n writing-mode: lr-tb;\r\n letter-spacing: normal;\r\n text-anchor: ${textAnchor};\r\n `);\r\n }\r\n textNode.appendChild(document.createTextNode(elementName));\r\n textElem.appendChild(textNode);\r\n\r\n // Charge\r\n if (charge) {\r\n let chargeElem = this.createSubSuperScripts(getChargeText(charge), 'super');\r\n textNode.appendChild(chargeElem);\r\n }\r\n\r\n let isotopeText = '0';\r\n\r\n if (isotope > 0) {\r\n let isotopeElem = this.createSubSuperScripts(isotope.toString(), 'super');\r\n textNode.appendChild(isotopeElem);\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') &&\r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = {\r\n '0O': {\r\n element: 'O',\r\n count: 2,\r\n hydrogenCount: 0,\r\n previousElement: 'C',\r\n charge: ''\r\n }\r\n }\r\n charge = 0;\r\n }\r\n\r\n if (hydrogens > 0) {\r\n let hydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n hydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n hydrogenElem.appendChild(document.createTextNode('H'));\r\n textElem.appendChild(hydrogenElem);\r\n\r\n if (hydrogens > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogens, 'sub');\r\n hydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let element = attachedPseudoElement[key].element,\r\n elementCount = attachedPseudoElement[key].count,\r\n hydrogenCount = attachedPseudoElement[key].hydrogenCount,\r\n elementCharge = attachedPseudoElement[key].charge,\r\n pseudoElementElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoElementElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoElementElem.appendChild(document.createTextNode(element));\r\n pseudoElementElem.setAttributeNS(null, 'fill', this.themeManager.getColor(element));\r\n\r\n if (elementCharge !== 0) {\r\n let elementChargeElem = this.createSubSuperScripts(getChargeText(elementCharge), 'super');\r\n pseudoElementElem.appendChild(elementChargeElem);\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n let pseudoHydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoHydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoHydrogenElem.appendChild(document.createTextNode('H'));\r\n pseudoElementElem.appendChild(pseudoHydrogenElem);\r\n\r\n if (hydrogenCount > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogenCount, 'sub');\r\n pseudoHydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n if (elementCount > 1) {\r\n let elementCountElem = this.createSubSuperScripts(elementCount, 'sub');\r\n pseudoElementElem.appendChild(elementCountElem);\r\n }\r\n\r\n textElem.appendChild(pseudoElementElem);\r\n }\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * @param {Line} line the line object to create the wedge from\r\n */\r\n drawWedge(line) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l,\r\n end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness)),\r\n u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness)),\r\n v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness)),\r\n w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n let polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'),\r\n gradient = this.createGradient(line, l.x, l.y, r.x, r.y);\r\n polygon.setAttributeNS(null, 'points', `${t.x},${t.y} ${u.x},${u.y} ${v.x},${v.y} ${w.x},${w.y}`);\r\n polygon.setAttributeNS(null, 'fill', `url('#${gradient}')`);\r\n this.paths.push(polygon);\r\n }\r\n}\r\n\r\nmodule.exports = SvgWrapper;","class ThemeManager {\r\n constructor(colors, theme) {\r\n this.colors = colors;\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n if (key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.theme) {\r\n return this.theme[key];\r\n }\r\n }\r\n\r\n return this.theme['C'];\r\n }\r\n\r\n /**\r\n * Sets the theme to the specified string if it exists. If it does not, this\r\n * does nothing.\r\n *\r\n * @param {String} theme the name of the theme to switch to\r\n */\r\n setTheme(theme) {\r\n if (this.colors.hasOwnProperty(theme)) {\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n // TODO: this probably should notify those who are watching this theme\r\n // manager that the theme has changed so that colors can be changed\r\n // on the fly\r\n }\r\n}\r\n\r\nmodule.exports = ThemeManager;","/**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\nfunction getChargeText(charge) {\r\n console.log('in the utility version of getChargeText');\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n getChargeText,\r\n}","//@ts-check\r\n\r\n/** \r\n * A class representing a 2D vector.\r\n * \r\n * @property {Number} x The x component of the vector.\r\n * @property {Number} y The y component of the vector.\r\n */\r\nclass Vector2 {\r\n /**\r\n * The constructor of the class Vector2.\r\n *\r\n * @param {(Number|Vector2)} x The initial x coordinate value or, if the single argument, a Vector2 object.\r\n * @param {Number} y The initial y coordinate value.\r\n */\r\n constructor(x, y) {\r\n if (arguments.length == 0) {\r\n this.x = 0;\r\n this.y = 0;\r\n } else if (arguments.length == 1) {\r\n this.x = x.x;\r\n this.y = x.y;\r\n } else {\r\n this.x = x;\r\n this.y = y;\r\n }\r\n }\r\n\r\n /**\r\n * Clones this vector and returns the clone.\r\n *\r\n * @returns {Vector2} The clone of this vector.\r\n */\r\n clone() {\r\n return new Vector2(this.x, this.y);\r\n }\r\n\r\n /**\r\n * Returns a string representation of this vector.\r\n *\r\n * @returns {String} A string representation of this vector.\r\n */\r\n toString() {\r\n return '(' + this.x + ',' + this.y + ')';\r\n }\r\n\r\n /**\r\n * Add the x and y coordinate values of a vector to the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n add(vec) {\r\n this.x += vec.x;\r\n this.y += vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Subtract the x and y coordinate values of a vector from the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n subtract(vec) {\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Divide the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n divide(scalar) {\r\n this.x /= scalar;\r\n this.y /= scalar;\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Multiply the x and y coordinate values of this vector by the values of another vector.\r\n *\r\n * @param {Vector2} v A vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiply(v) {\r\n this.x *= v.x;\r\n this.y *= v.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Multiply the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiplyScalar(scalar) {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Inverts this vector. Same as multiply(-1.0).\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n invert() {\r\n this.x = -this.x;\r\n this.y = -this.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vector in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n angle() {\r\n return Math.atan2(this.y, this.x);\r\n }\r\n\r\n /**\r\n * Returns the euclidean distance between this vector and another vector.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Number} The euclidean distance between the two vectors.\r\n */\r\n distance(vec) {\r\n return Math.sqrt((vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y));\r\n }\r\n\r\n /**\r\n * Returns the squared euclidean distance between this vector and another vector. When only the relative distances of a set of vectors are needed, this is is less expensive than using distance(vec).\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} The squared euclidean distance of the two vectors.\r\n */\r\n distanceSq(vec) {\r\n return (vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to the coordinate system.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to the coordinate system.\r\n */\r\n clockwise(vec) {\r\n let a = this.y * vec.x;\r\n let b = this.x * vec.y;\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to an arbitrary third vector.\r\n *\r\n * @param {Vector2} center The central vector.\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to an arbitrary third vector.\r\n */\r\n relativeClockwise(center, vec) {\r\n let a = (this.y - center.y) * (vec.x - center.x);\r\n let b = (this.x - center.x) * (vec.y - center.y);\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Rotates this vector by a given number of radians around the origin of the coordinate system.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotate(angle) {\r\n let tmp = new Vector2(0, 0);\r\n let cosAngle = Math.cos(angle);\r\n let sinAngle = Math.sin(angle);\r\n\r\n tmp.x = this.x * cosAngle - this.y * sinAngle;\r\n tmp.y = this.x * sinAngle + this.y * cosAngle;\r\n \r\n this.x = tmp.x;\r\n this.y = tmp.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this vector around another vector.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @param {Vector2} vec The vector which is used as the rotational center.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateAround(angle, vec) {\r\n let s = Math.sin(angle);\r\n let c = Math.cos(angle);\r\n\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n let x = this.x * c - this.y * s;\r\n let y = this.x * s + this.y * c;\r\n\r\n this.x = x + vec.x;\r\n this.y = y + vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate a vector around a given center to the same angle as another vector (so that the two vectors and the center are in a line, with both vectors on one side of the center), keeps the distance from this vector to the center.\r\n *\r\n * @param {Vector2} vec The vector to rotate this vector to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} [offsetAngle=0.0] An additional amount of radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateTo(vec, center, offsetAngle = 0.0) {\r\n // Problem if this is first position\r\n this.x += 0.001;\r\n this.y -= 0.001;\r\n\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n\r\n this.rotateAround(angle + offsetAngle, center);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates the vector away from a specified vector around a center.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n */\r\n rotateAwayFrom(vec, center, angle) {\r\n this.rotateAround(angle, center);\r\n \r\n let distSqA = this.distanceSq(vec);\r\n \r\n this.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = this.distanceSq(vec);\r\n\r\n // If it was rotated towards the other vertex, rotate in other direction by same amount.\r\n if (distSqB < distSqA) {\r\n this.rotateAround(2.0 * angle, center);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector away from a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateAwayFromAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB < distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector towards a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated towards to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateTowardsAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB > distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the angles between this vector and another vector around a common center of rotation.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @param {Vector2} center The center of rotation.\r\n * @returns {Number} The angle between this vector and another vector around a center of rotation in radians.\r\n */\r\n getRotateToAngle(vec, center) {\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n \r\n return Number.isNaN(angle) ? 0.0 : angle;\r\n }\r\n\r\n /**\r\n * Checks whether a vector lies within a polygon spanned by a set of vectors.\r\n *\r\n * @param {Vector2[]} polygon An array of vectors spanning the polygon.\r\n * @returns {Boolean} A boolean indicating whether or not this vector is within a polygon.\r\n */\r\n isInPolygon(polygon) {\r\n let inside = false;\r\n\r\n // Its not always a given, that the polygon is convex (-> sugars)\r\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\r\n if (((polygon[i].y > this.y) != (polygon[j].y > this.y)) &&\r\n (this.x < (polygon[j].x - polygon[i].x) * (this.y - polygon[i].y) /\r\n (polygon[j].y - polygon[i].y) + polygon[i].x)) {\r\n inside = !inside;\r\n }\r\n }\r\n\r\n\r\n return inside;\r\n }\r\n\r\n /**\r\n * Returns the length of this vector.\r\n *\r\n * @returns {Number} The length of this vector.\r\n */\r\n length() {\r\n return Math.sqrt((this.x * this.x) + (this.y * this.y));\r\n }\r\n\r\n /**\r\n * Returns the square of the length of this vector.\r\n *\r\n * @returns {Number} The square of the length of this vector.\r\n */\r\n lengthSq() {\r\n return (this.x * this.x) + (this.y * this.y);\r\n }\r\n\r\n /**\r\n * Normalizes this vector.\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n normalize() {\r\n this.divide(this.length());\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns a normalized copy of this vector.\r\n *\r\n * @returns {Vector2} A normalized copy of this vector.\r\n */\r\n normalized() {\r\n return Vector2.divideScalar(this, this.length());\r\n }\r\n\r\n /**\r\n * Calculates which side of a line spanned by two vectors this vector is.\r\n *\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} A number indicating the side of this vector, given a line spanned by two other vectors.\r\n */\r\n whichSide(vecA, vecB) {\r\n return (this.x - vecA.x) * (vecB.y - vecA.y) - (this.y - vecA.y) * (vecB.x - vecA.x);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is on the same side of a line spanned by two vectors as another vector.\r\n *\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @param {Vector2} vecC A vector to check whether or not it is on the same side as this vector.\r\n * @returns {Boolean} Returns a boolean indicating whether or not this vector is on the same side as another vector.\r\n */\r\n sameSideAs(vecA, vecB, vecC) {\r\n let d = this.whichSide(vecA, vecB);\r\n let dRef = vecC.whichSide(vecA, vecB);\r\n\r\n return d < 0 && dRef < 0 || d == 0 && dRef == 0 || d > 0 && dRef > 0;\r\n }\r\n\r\n /**\r\n * Adds two vectors and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A summand.\r\n * @param {Vector2} vecB A summand.\r\n * @returns {Vector2} Returns the sum of two vectors.\r\n */\r\n static add(vecA, vecB) {\r\n return new Vector2(vecA.x + vecB.x, vecA.y + vecB.y);\r\n }\r\n\r\n /**\r\n * Subtracts one vector from another and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The minuend.\r\n * @param {Vector2} vecB The subtrahend.\r\n * @returns {Vector2} Returns the difference of two vectors.\r\n */\r\n static subtract(vecA, vecB) {\r\n return new Vector2(vecA.x - vecB.x, vecA.y - vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiply(vecA, vecB) {\r\n return new Vector2(vecA.x * vecB.x, vecA.y * vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vec A vector.\r\n * @param {Number} scalar A scalar.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiplyScalar(vec, scalar) {\r\n return new Vector2(vec.x, vec.y).multiplyScalar(scalar);\r\n }\r\n\r\n /**\r\n * Returns the midpoint of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2} The midpoint of the line spanned by two vectors.\r\n */\r\n static midpoint(vecA, vecB) {\r\n return new Vector2((vecA.x + vecB.x) / 2, (vecA.y + vecB.y) / 2);\r\n }\r\n\r\n /**\r\n * Returns the normals of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two normals, each represented by a vector.\r\n */\r\n static normals(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n new Vector2(-delta.y, delta.x),\r\n new Vector2(delta.y, -delta.x)\r\n ];\r\n }\r\n\r\n /**\r\n * Returns the unit (normalized normal) vectors of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two unit vectors.\r\n */\r\n static units(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n (new Vector2(-delta.y, delta.x)).normalize(),\r\n (new Vector2(delta.y, -delta.x)).normalize()\r\n ];\r\n }\r\n\r\n /**\r\n * Divides a vector by another vector and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Vector2} vecB The divisor.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divide(vecA, vecB) {\r\n return new Vector2(vecA.x / vecB.x, vecA.y / vecB.y);\r\n }\r\n\r\n /**\r\n * Divides a vector by a scalar and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Number} s The scalar.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divideScalar(vecA, s) {\r\n return new Vector2(vecA.x / s, vecA.y / s);\r\n }\r\n\r\n /**\r\n * Returns the dot product of two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The dot product of two vectors.\r\n */\r\n static dot(vecA, vecB) {\r\n return vecA.x * vecB.x + vecA.y * vecB.y;\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The angle between two vectors in radians.\r\n */\r\n static angle(vecA, vecB) {\r\n let dot = Vector2.dot(vecA, vecB);\r\n\r\n return Math.acos(dot / (vecA.length() * vecB.length()));\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors based on a third vector in between.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A (central) vector.\r\n * @param {Vector2} vecC A vector.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static threePointangle(vecA, vecB, vecC) {\r\n let ab = Vector2.subtract(vecB, vecA);\r\n let bc = Vector2.subtract(vecC, vecB);\r\n let abLength = vecA.distance(vecB);\r\n let bcLength = vecB.distance(vecC);\r\n\r\n return Math.acos(Vector2.dot(ab, bc) / (abLength * bcLength));\r\n }\r\n \r\n /**\r\n * Returns the scalar projection of a vector on another vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The vector to be projected.\r\n * @param {Vector2} vecB The vector to be projection upon.\r\n * @returns {Number} The scalar component.\r\n */\r\n static scalarProjection(vecA, vecB) {\r\n let unit = vecB.normalized();\r\n \r\n return Vector2.dot(vecA, unit);\r\n }\r\n\r\n /**\r\n * Returns the average vector (normalized) of the input vectors.\r\n *\r\n * @static\r\n * @param {Array} vecs An array containing vectors.\r\n * @returns {Vector2} The resulting vector (normalized).\r\n */\r\n static averageDirection(vecs) {\r\n let avg = new Vector2(0.0, 0.0);\r\n\r\n for (var i = 0; i < vecs.length; i++) {\r\n let vec = vecs[i];\r\n avg.add(vec);\r\n }\r\n\r\n return avg.normalize();\r\n }\r\n}\r\n\r\nmodule.exports = Vector2;","//@ts-check\r\nconst MathHelper = require('./MathHelper')\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Atom = require('./Atom')\r\nconst VertexState = require('./VertexState')\r\n\r\n/** \r\n * A class representing a vertex.\r\n * \r\n * @property {Number} id The id of this vertex.\r\n * @property {Atom} value The atom associated with this vertex.\r\n * @property {Vector2} position The position of this vertex.\r\n * @property {Vector2} previousPosition The position of the previous vertex.\r\n * @property {Number|null} parentVertexId The id of the previous vertex.\r\n * @property {Number[]} children The ids of the children of this vertex.\r\n * @property {Number[]} spanningTreeChildren The ids of the children of this vertex as defined in the spanning tree defined by the SMILES.\r\n * @property {Number[]} edges The ids of edges associated with this vertex.\r\n * @property {Boolean} positioned A boolean indicating whether or not this vertex has been positioned.\r\n * @property {Number} angle The angle of this vertex.\r\n * @property {Number} dir The direction of this vertex.\r\n * @property {Number} neighbourCount The number of neighbouring vertices.\r\n * @property {Number[]} neighbours The vertex ids of neighbouring vertices.\r\n * @property {String[]} neighbouringElements The element symbols associated with neighbouring vertices.\r\n * @property {Boolean} forcePositioned A boolean indicating whether or not this vertex was positioned using a force-based approach.\r\n * @property {Number} vertexState enum of VertexState for DFS.\r\n */\r\n\r\nclass Vertex {\r\n /**\r\n * The constructor for the class Vertex.\r\n *\r\n * @param {Atom} value The value associated with this vertex.\r\n * @param {Number} [x=0] The initial x coordinate of the positional vector of this vertex.\r\n * @param {Number} [y=0] The initial y coordinate of the positional vector of this vertex.\r\n */\r\n constructor(value, x = 0, y = 0) {\r\n this.id = null;\r\n this.value = value;\r\n this.position = new Vector2(x ? x : 0, y ? y : 0);\r\n this.previousPosition = new Vector2(0, 0);\r\n this.parentVertexId = null;\r\n this.children = Array();\r\n this.spanningTreeChildren = Array();\r\n this.edges = Array();\r\n this.positioned = false;\r\n this.angle = null;\r\n this.dir = 1.0;\r\n this.neighbourCount = 0;\r\n this.neighbours = Array();\r\n this.neighbouringElements = Array();\r\n this.forcePositioned = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n this.component = -1;\r\n this.digits = [];\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex.\r\n * \r\n * @param {Number} x The x component of the coordinates.\r\n * @param {Number} y The y component of the coordinates.\r\n * \r\n */\r\n setPosition(x, y) {\r\n this.position.x = x;\r\n this.position.y = y;\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex from a Vector2.\r\n * \r\n * @param {Vector2} v A 2D vector.\r\n * \r\n */\r\n setPositionFromVector(v) {\r\n this.position.x = v.x;\r\n this.position.y = v.y;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n */\r\n addChild(vertexId) {\r\n this.children.push(vertexId);\r\n this.neighbours.push(vertexId);\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex as the second child of the neighbours array,\r\n * except this vertex is the first vertex of the SMILE string, then it is added as the first.\r\n * This is used to get the correct ordering of neighbours for parity calculations.\r\n * If a hydrogen is implicitly attached to the chiral center, insert as the third child.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n * @param {Number} ringbondIndex The index of the ringbond.\r\n */\r\n addRingbondChild(vertexId, ringbondIndex) {\r\n this.children.push(vertexId);\r\n\r\n if (this.value.bracket) {\r\n let index = 1;\r\n\r\n if (this.id === 0 && this.value.bracket.hcount === 0) {\r\n index = 0;\r\n }\r\n \r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 0) {\r\n index = 2;\r\n }\r\n\r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 2;\r\n } else {\r\n index = 3;\r\n }\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 0) {\r\n index = 1;\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 1;\r\n } else {\r\n index = 2;\r\n }\r\n }\r\n \r\n this.neighbours.splice(index, 0, vertexId);\r\n } else {\r\n this.neighbours.push(vertexId);\r\n }\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Set the vertex id of the parent.\r\n * \r\n * @param {Number} parentVertexId The parents vertex id.\r\n */\r\n setParentVertexId(parentVertexId) {\r\n this.neighbourCount++;\r\n this.parentVertexId = parentVertexId;\r\n this.neighbours.push(parentVertexId);\r\n }\r\n\r\n /**\r\n * Returns true if this vertex is terminal (has no parent or child vertices), otherwise returns false. Always returns true if associated value has property hasAttachedPseudoElements set to true.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not this vertex is terminal.\r\n */\r\n isTerminal() {\r\n if (this.value.hasAttachedPseudoElements) {\r\n return true;\r\n }\r\n\r\n return (this.parentVertexId === null && this.children.length < 2) || this.children.length === 0;\r\n }\r\n\r\n /**\r\n * Clones this vertex and returns the clone.\r\n *\r\n * @returns {Vertex} A clone of this vertex.\r\n */\r\n clone() {\r\n let clone = new Vertex(this.value, this.position.x, this.position.y);\r\n clone.id = this.id;\r\n clone.previousPosition = new Vector2(this.previousPosition.x, this.previousPosition.y);\r\n clone.parentVertexId = this.parentVertexId;\r\n clone.children = ArrayHelper.clone(this.children);\r\n clone.spanningTreeChildren = ArrayHelper.clone(this.spanningTreeChildren);\r\n clone.edges = ArrayHelper.clone(this.edges);\r\n clone.positioned = this.positioned;\r\n clone.angle = this.angle;\r\n clone.forcePositioned = this.forcePositioned;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns true if this vertex and the supplied vertex both have the same id, else returns false.\r\n *\r\n * @param {Vertex} vertex The vertex to check.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices have the same id.\r\n */\r\n equals(vertex) {\r\n return this.id === vertex.id;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vertexes positional vector. If a reference vector is supplied in relations to this vector, else in relations to the coordinate system.\r\n *\r\n * @param {Vector2} [referenceVector=null] - The reference vector.\r\n * @param {Boolean} [returnAsDegrees=false] - If true, returns angle in degrees, else in radians.\r\n * @returns {Number} The angle of this vertex.\r\n */\r\n getAngle(referenceVector = null, returnAsDegrees = false) {\r\n let u = null;\r\n\r\n if (!referenceVector) {\r\n u = Vector2.subtract(this.position, this.previousPosition);\r\n } else {\r\n u = Vector2.subtract(this.position, referenceVector);\r\n }\r\n\r\n if (returnAsDegrees) {\r\n return MathHelper.toDeg(u.angle());\r\n }\r\n\r\n return u.angle();\r\n }\r\n\r\n /**\r\n * Returns the suggested text direction when text is added at the position of this vertex.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @returns {String} The suggested direction of the text.\r\n */\r\n getTextDirection(vertices) {\r\n let neighbours = this.getDrawnNeighbours(vertices);\r\n let angles = Array();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n angles.push(this.getAngle(vertices[neighbours[i]].position));\r\n }\r\n\r\n let textAngle = MathHelper.meanAngle(angles);\r\n\r\n // Round to 0, 90, 180 or 270 degree\r\n let halfPi = Math.PI / 2.0;\r\n textAngle = Math.round(Math.round(textAngle / halfPi) * halfPi);\r\n\r\n if (textAngle === 2) {\r\n return 'down';\r\n } else if (textAngle === -2) {\r\n return 'up';\r\n } else if (textAngle === 0 || textAngle === -0) {\r\n return 'right'; // is checking for -0 necessary?\r\n } else if (textAngle === 3 || textAngle === -3) {\r\n return 'left';\r\n } else {\r\n return 'down'; // default to down\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices.\r\n *\r\n * @param {Number} [vertexId=null] If a value is supplied, the vertex with this id is excluded from the returned indices.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices.\r\n */\r\n getNeighbours(vertexId = null) {\r\n if (vertexId === null) {\r\n return this.neighbours.slice();\r\n }\r\n\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (this.neighbours[i] !== vertexId) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices that will be drawn (vertex.value.isDrawn === true).\r\n * \r\n * @param {Vertex[]} vertices An array containing the vertices associated with the current molecule.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices that will be drawn.\r\n */\r\n getDrawnNeighbours(vertices) {\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (vertices[this.neighbours[i]].value.isDrawn) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns the number of neighbours of this vertex.\r\n *\r\n * @returns {Number} The number of neighbours.\r\n */\r\n getNeighbourCount() {\r\n return this.neighbourCount;\r\n }\r\n\r\n /**\r\n * Returns a list of ids of vertices neighbouring this one in the original spanning tree, excluding the ringbond connections.\r\n *\r\n * @param {Number} [vertexId=null] If supplied, the vertex with this id is excluded from the array returned.\r\n * @returns {Number[]} An array containing the ids of the neighbouring vertices.\r\n */\r\n getSpanningTreeNeighbours(vertexId = null) {\r\n let neighbours = Array();\r\n\r\n for (let i = 0; i < this.spanningTreeChildren.length; i++) {\r\n if (vertexId === undefined || vertexId != this.spanningTreeChildren[i]) {\r\n neighbours.push(this.spanningTreeChildren[i]);\r\n }\r\n }\r\n\r\n if (this.parentVertexId != null) {\r\n if (vertexId === undefined || vertexId != this.parentVertexId) {\r\n neighbours.push(this.parentVertexId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Gets the next vertex in the ring in opposide direction to the supplied vertex id.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @param {Number} ringId The id of the ring containing this vertex.\r\n * @param {Number} previousVertexId The id of the previous vertex. The next vertex will be opposite from the vertex with this id as seen from this vertex.\r\n * @returns {Number} The id of the next vertex in the ring.\r\n */\r\n getNextInRing(vertices, ringId, previousVertexId) {\r\n let neighbours = this.getNeighbours();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (ArrayHelper.contains(vertices[neighbours[i]].value.rings, {\r\n value: ringId\r\n }) &&\r\n neighbours[i] != previousVertexId) {\r\n return neighbours[i];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n\r\nmodule.exports = Vertex;","//@ts-check\r\n\r\nclass VertexState {\r\n\r\n /**\r\n * Enum values of Vertex State for DFS\r\n * @return {{NOT_FOUND: number, OPEN: number, CLOSED: number, FULLY_CLOSED: number}}\r\n */\r\n static get VALUES() {\r\n return { NOT_FOUND: 0, OPEN: 1, CLOSED: 2, FULLY_CLOSED: 3 };\r\n }\r\n}\r\n\r\nmodule.exports = VertexState;\r\n"]} \ No newline at end of file +{"version":3,"sources":["node_modules/browser-pack/_prelude.js","app.js","src/ArrayHelper.js","src/Atom.js","src/CanvasWrapper.js","src/DecayPoint.js","src/DecayState.js","src/Direction.js","src/Drawer.js","src/Edge.js","src/Graph.js","src/Line.js","src/MathHelper.js","src/MutableBoolean.js","src/MutableCounter.js","src/Neighbour.js","src/Node.js","src/Parser.js","src/Ring.js","src/RingConnection.js","src/SSSR.js","src/SequenceType.js","src/SmallGraph.js","src/SvgDrawer.js","src/SvgWrapper.js","src/ThemeManager.js","src/UtilityFunctions.js","src/Vector2.js","src/Vertex.js","src/VertexState.js"],"names":[],"mappings":"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","file":"smiles-drawer.min.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i {\r\n const context = canvas.getContext('2d');\r\n context.clearRect(0, 0, canvas.width, canvas.height);\r\n })\r\n};\r\n\r\n/**\r\n* Parses the entered smiles string.\r\n*\r\n* @static\r\n* @param {String} smiles A SMILES string.\r\n* @param {Function} successCallback A callback that is called on success with the parse tree.\r\n* @param {Function} errorCallback A callback that is called with the error object on error.\r\n*/\r\nSmilesDrawer.parse = function(smiles, successCallback, errorCallback) {\r\n try {\r\n if (successCallback) {\r\n successCallback(Parser.parse(smiles));\r\n }\r\n } catch (err) {\r\n if (errorCallback) {\r\n errorCallback(err);\r\n }\r\n }\r\n};\r\n\r\nif (canUseDOM) {\r\n window.SmilesDrawer = SmilesDrawer;\r\n}\r\n\r\n// There be dragons (polyfills)\r\n\r\nif (!Array.prototype.fill) {\r\nObject.defineProperty(Array.prototype, 'fill', {\r\n value: function(value) {\r\n\r\n // Steps 1-2.\r\n if (this == null) {\r\n throw new TypeError('this is null or not defined');\r\n }\r\n\r\n var O = Object(this);\r\n\r\n // Steps 3-5.\r\n var len = O.length >>> 0;\r\n\r\n // Steps 6-7.\r\n var start = arguments[1];\r\n var relativeStart = start >> 0;\r\n\r\n // Step 8.\r\n var k = relativeStart < 0 ?\r\n Math.max(len + relativeStart, 0) :\r\n Math.min(relativeStart, len);\r\n\r\n // Steps 9-10.\r\n var end = arguments[2];\r\n var relativeEnd = end === undefined ?\r\n len : end >> 0;\r\n\r\n // Step 11.\r\n var final = relativeEnd < 0 ?\r\n Math.max(len + relativeEnd, 0) :\r\n Math.min(relativeEnd, len);\r\n\r\n // Step 12.\r\n while (k < final) {\r\n O[k] = value;\r\n k++;\r\n }\r\n\r\n // Step 13.\r\n return O;\r\n }\r\n});\r\n}\r\n\r\nmodule.exports = SmilesDrawer;","//@ts-check\r\n\r\n/** \r\n * A static class containing helper functions for array-related tasks. \r\n */\r\nclass ArrayHelper {\r\n /**\r\n * Clone an array or an object. If an object is passed, a shallow clone will be created.\r\n *\r\n * @static\r\n * @param {*} arr The array or object to be cloned.\r\n * @returns {*} A clone of the array or object.\r\n */\r\n static clone(arr) {\r\n let out = Array.isArray(arr) ? Array() : {};\r\n \r\n for (let key in arr) {\r\n let value = arr[key];\r\n \r\n if (typeof value.clone === 'function') {\r\n out[key] = value.clone();\r\n }\r\n else {\r\n out[key] = (typeof value === 'object') ? ArrayHelper.clone(value) : value;\r\n }\r\n }\r\n \r\n return out;\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not the two arrays contain the same elements.\r\n * Only supports 1d, non-nested arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not the two arrays contain the same elements.\r\n */\r\n static equals(arrA, arrB) {\r\n if (arrA.length !== arrB.length) {\r\n return false;\r\n }\r\n\r\n let tmpA = arrA.slice().sort();\r\n let tmpB = arrB.slice().sort();\r\n\r\n for (let i = 0; i < tmpA.length; i++) {\r\n if (tmpA[i] !== tmpB[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns a string representation of an array. If the array contains objects with an id property, the id property is printed for each of the elements.\r\n *\r\n * @static\r\n * @param {Object[]} arr An array.\r\n * @param {*} arr[].id If the array contains an object with the property 'id', the properties value is printed. Else, the array elements value is printend.\r\n * @returns {String} A string representation of the array.\r\n */\r\n static print(arr) {\r\n if (arr.length == 0) {\r\n return '';\r\n }\r\n\r\n let s = '(';\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n s += arr[i].id ? arr[i].id + ', ' : arr[i] + ', ';\r\n }\r\n\r\n s = s.substring(0, s.length - 2);\r\n\r\n return s + ')';\r\n }\r\n\r\n /**\r\n * Run a function for each element in the array. The element is supplied as an argument for the callback function\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Function} callback The callback function that is called for each element.\r\n */\r\n static each(arr, callback) {\r\n for (let i = 0; i < arr.length; i++) {\r\n callback(arr[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Return the array element from an array containing objects, where a property of the object is set to a given value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {(String|Number)} property A property contained within an object in the array.\r\n * @param {(String|Number)} value The value of the property.\r\n * @returns {*} The array element matching the value.\r\n */\r\n static get(arr, property, value) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][property] == value) {\r\n return arr[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains a given value. the options object passed as a second argument can contain three properties. value: The value to be searched for. property: The property that is to be searched for a given value. func: A function that is used as a callback to return either true or false in order to do a custom comparison.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {Object} options See method description.\r\n * @param {*} options.value The value for which to check.\r\n * @param {String} [options.property=undefined] The property on which to check.\r\n * @param {Function} [options.func=undefined] A custom property function.\r\n * @returns {Boolean} A boolean whether or not the array contains a value.\r\n */\r\n static contains(arr, options) {\r\n if (!options.property && !options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] == options.value) {\r\n return true;\r\n }\r\n }\r\n } else if (options.func) {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (options.func(arr[i])) {\r\n return true;\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i][options.property] == options.value) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array containing the intersection between two arrays. That is, values that are common to both arrays.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The intersecting vlaues.\r\n */\r\n static intersection(arrA, arrB) {\r\n let intersection = [];\r\n \r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n intersection.push(arrA[i]);\r\n }\r\n }\r\n }\r\n\r\n return intersection;\r\n }\r\n\r\n /**\r\n * Returns an array of unique elements contained in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @returns {Array} An array of unique elements contained within the array supplied as an argument.\r\n */\r\n static unique(arr) {\r\n let contains = {};\r\n return arr.filter(function (i) {\r\n // using !== instead of hasOwnProperty (http://andrew.hedges.name/experiments/in/)\r\n return contains[i] !== undefined ? false : (contains[i] = true);\r\n });\r\n }\r\n\r\n /**\r\n * Count the number of occurences of a value in an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be counted.\r\n * @returns {Number} The number of occurences of a value in the array.\r\n */\r\n static count(arr, value) {\r\n let count = 0;\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] === value) {\r\n count++;\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * Toggles the value of an array. If a value is not contained in an array, the array returned will contain all the values of the original array including the value. If a value is contained in an array, the array returned will contain all the values of the original array excluding the value.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be toggled.\r\n * @returns {Array} The toggled array.\r\n */\r\n static toggle(arr, value) {\r\n let newArr = Array();\r\n\r\n let removed = false;\r\n for (let i = 0; i < arr.length; i++) {\r\n // Do not copy value if it exists\r\n if (arr[i] !== value) {\r\n newArr.push(arr[i]);\r\n } else {\r\n // The element was not copied to the new array, which\r\n // means it was removed\r\n removed = true;\r\n }\r\n }\r\n\r\n // If the element was not removed, then it was not in the array\r\n // so add it\r\n if (!removed) {\r\n newArr.push(value);\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n /**\r\n * Remove a value from an array.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} A new array with the element with a given value removed.\r\n */\r\n static remove(arr, value) {\r\n let tmp = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n if (arr[i] !== value) {\r\n tmp.push(arr[i]);\r\n }\r\n }\r\n\r\n return tmp;\r\n }\r\n\r\n /**\r\n * Remove a value from an array with unique values.\r\n *\r\n * @static\r\n * @param {Array} arr An array.\r\n * @param {*} value A value to be removed.\r\n * @returns {Array} An array with the element with a given value removed.\r\n */\r\n static removeUnique(arr, value) {\r\n let index = arr.indexOf(value);\r\n\r\n if (index > -1) {\r\n arr.splice(index, 1);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Remove all elements contained in one array from another array.\r\n *\r\n * @static\r\n * @param {Array} arrA The array to be filtered.\r\n * @param {Array} arrB The array containing elements that will be removed from the other array.\r\n * @returns {Array} The filtered array.\r\n */\r\n static removeAll(arrA, arrB) {\r\n return arrA.filter(function (item) {\r\n return arrB.indexOf(item) === -1;\r\n });\r\n }\r\n\r\n /**\r\n * Merges two arrays and returns the result. The first array will be appended to the second array.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Array} The merged array.\r\n */\r\n static merge(arrA, arrB) {\r\n let arr = new Array(arrA.length + arrB.length);\r\n\r\n for (let i = 0; i < arrA.length; i++) {\r\n arr[i] = arrA[i];\r\n }\r\n\r\n for (let i = 0; i < arrB.length; i++) {\r\n arr[arrA.length + i] = arrB[i];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Checks whether or not an array contains all the elements of another array, without regard to the order.\r\n *\r\n * @static\r\n * @param {Array} arrA An array.\r\n * @param {Array} arrB An array.\r\n * @returns {Boolean} A boolean indicating whether or not both array contain the same elements.\r\n */\r\n static containsAll(arrA, arrB) {\r\n let containing = 0;\r\n for (let i = 0; i < arrA.length; i++) {\r\n for (let j = 0; j < arrB.length; j++) {\r\n if (arrA[i] === arrB[j]) {\r\n containing++;\r\n }\r\n }\r\n }\r\n\r\n return containing === arrB.length;\r\n }\r\n \r\n /**\r\n * Sort an array of atomic number information. Where the number is indicated as x, x.y, x.y.z, ...\r\n *\r\n * @param {Object[]} arr An array of vertex ids with their associated atomic numbers.\r\n * @param {Number} arr[].vertexId A vertex id.\r\n * @param {String} arr[].atomicNumber The atomic number associated with the vertex id.\r\n * @returns {Object[]} The array sorted by atomic number. Example of an array entry: { atomicNumber: 2, vertexId: 5 }.\r\n */\r\n static sortByAtomicNumberDesc(arr) {\r\n let map = arr.map(function(e, i) {\r\n return { index: i, value: e.atomicNumber.split('.').map(Number) };\r\n });\r\n\r\n map.sort(function(a, b) {\r\n let min = Math.min(b.value.length, a.value.length);\r\n let i = 0;\r\n \r\n while(i < min && b.value[i] === a.value[i]) {\r\n i++;\r\n }\r\n\r\n return i === min ? b.value.length - a.value.length : b.value[i] - a.value[i];\r\n });\r\n\r\n return map.map(function(e) {\r\n return arr[e.index];\r\n });\r\n }\r\n\r\n /**\r\n * Copies a an n-dimensional array.\r\n * \r\n * @param {Array} arr The array to be copied.\r\n * @returns {Array} The copy.\r\n */\r\n static deepCopy(arr) {\r\n let newArr = Array();\r\n\r\n for (let i = 0; i < arr.length; i++) {\r\n let item = arr[i];\r\n\r\n if (item instanceof Array) {\r\n newArr[i] = ArrayHelper.deepCopy(item);\r\n } else {\r\n newArr[i] = item;\r\n }\r\n }\r\n\r\n return newArr;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = ArrayHelper;","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper');\r\n\r\n/** \r\n * A class representing an atom.\r\n * \r\n * @property {String} element The element symbol of this atom. Single-letter symbols are always uppercase. Examples: H, C, F, Br, Si, ...\r\n * @property {Boolean} drawExplicit A boolean indicating whether or not this atom is drawn explicitly (for example, a carbon atom). This overrides the default behaviour.\r\n * @property {Object[]} ringbonds An array containing the ringbond ids and bond types as specified in the original SMILE.\r\n * @property {String} branchBond The branch bond as defined in the SMILES.\r\n * @property {Number} ringbonds[].id The ringbond id as defined in the SMILES.\r\n * @property {String} ringbonds[].bondType The bond type of the ringbond as defined in the SMILES.\r\n * @property {Number[]} rings The ids of rings which contain this atom.\r\n * @property {String} bondType The bond type associated with this array. Examples: -, =, #, ...\r\n * @property {Boolean} isBridge A boolean indicating whether or not this atom is part of a bridge in a bridged ring (contained by the largest ring).\r\n * @property {Boolean} isBridgeNode A boolean indicating whether or not this atom is a bridge node (a member of the largest ring in a bridged ring which is connected to a bridge-atom).\r\n * @property {Number[]} originalRings Used to back up rings when they are replaced by a bridged ring.\r\n * @property {Number} bridgedRing The id of the bridged ring if the atom is part of a bridged ring.\r\n * @property {Number[]} anchoredRings The ids of the rings that are anchored to this atom. The centers of anchored rings are translated when this atom is translated.\r\n * @property {Object} bracket If this atom is defined as a bracket atom in the original SMILES, this object contains all the bracket information. Example: { hcount: {Number}, charge: ['--', '-', '+', '++'], isotope: {Number} }.\r\n * @property {Number} plane Specifies on which \"plane\" the atoms is in stereochemical deptictions (-1 back, 0 middle, 1 front).\r\n * @property {Object[]} attachedPseudoElements A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @property {String} attachedPseudoElement[].element The element symbol.\r\n * @property {Number} attachedPseudoElement[].count The number of occurences that match the key.\r\n * @property {Number} attachedPseudoElement[].hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n * @property {Boolean} hasAttachedPseudoElements A boolean indicating whether or not this attom will be drawn with an attached pseudo element or concatinated elements.\r\n * @property {Boolean} isDrawn A boolean indicating whether or not this atom is drawn. In contrast to drawExplicit, the bond is drawn neither.\r\n * @property {Boolean} isConnectedToRing A boolean indicating whether or not this atom is directly connected (but not a member of) a ring.\r\n * @property {String[]} neighbouringElements An array containing the element symbols of neighbouring atoms.\r\n * @property {Boolean} isPartOfAromaticRing A boolean indicating whether or not this atom is part of an explicitly defined aromatic ring. Example: c1ccccc1.\r\n * @property {Number} bondCount The number of bonds in which this atom is participating.\r\n * @property {String} chirality The chirality of this atom if it is a stereocenter (R or S).\r\n * @property {Number} priority The priority of this atom acording to the CIP rules, where 0 is the highest priority.\r\n * @property {Boolean} mainChain A boolean indicating whether or not this atom is part of the main chain (used for chirality).\r\n * @property {String} hydrogenDirection The direction of the hydrogen, either up or down. Only for stereocenters with and explicit hydrogen.\r\n * @property {Number} subtreeDepth The depth of the subtree coming from a stereocenter.\r\n */\r\nclass Atom {\r\n /**\r\n * The constructor of the class Atom.\r\n *\r\n * @param {String} element The one-letter code of the element.\r\n * @param {String} [bondType='-'] The type of the bond associated with this atom.\r\n */\r\n constructor(element, bondType = '-') {\r\n this.element = element.length === 1 ? element.toUpperCase() : element;\r\n this.drawExplicit = false;\r\n this.ringbonds = Array();\r\n this.rings = Array();\r\n this.bondType = bondType;\r\n this.branchBond = null;\r\n this.isBridge = false;\r\n this.isBridgeNode = false;\r\n this.originalRings = Array();\r\n this.bridgedRing = null;\r\n this.anchoredRings = Array();\r\n this.bracket = null;\r\n this.plane = 0;\r\n this.attachedPseudoElements = {};\r\n this.hasAttachedPseudoElements = false;\r\n this.isDrawn = true;\r\n this.isConnectedToRing = false;\r\n this.neighbouringElements = Array();\r\n this.isPartOfAromaticRing = element !== this.element;\r\n this.bondCount = 0;\r\n this.chirality = '';\r\n this.isStereoCenter = false;\r\n this.priority = 0;\r\n this.mainChain = false;\r\n this.hydrogenDirection = 'down';\r\n this.subtreeDepth = 1;\r\n this.hasHydrogen = false;\r\n }\r\n\r\n /**\r\n * Adds a neighbouring element to this atom.\r\n * \r\n * @param {String} element A string representing an element.\r\n */\r\n addNeighbouringElement(element) {\r\n this.neighbouringElements.push(element);\r\n }\r\n\r\n /**\r\n * Attaches a pseudo element (e.g. Ac) to the atom.\r\n * @param {String} element The element identifier (e.g. Br, C, ...).\r\n * @param {String} previousElement The element that is part of the main chain (not the terminals that are converted to the pseudo element or concatinated).\r\n * @param {Number} [hydrogenCount=0] The number of hydrogens for the element.\r\n * @param {Number} [charge=0] The charge for the element.\r\n */\r\n attachPseudoElement(element, previousElement, hydrogenCount = 0, charge = 0) {\r\n if (hydrogenCount === null) {\r\n hydrogenCount = 0;\r\n }\r\n\r\n if (charge === null) {\r\n charge = 0;\r\n }\r\n\r\n let key = hydrogenCount + element + charge;\r\n\r\n if (this.attachedPseudoElements[key]) {\r\n this.attachedPseudoElements[key].count += 1;\r\n } else {\r\n this.attachedPseudoElements[key] = {\r\n element: element,\r\n count: 1,\r\n hydrogenCount: hydrogenCount,\r\n previousElement: previousElement,\r\n charge: charge\r\n };\r\n }\r\n\r\n this.hasAttachedPseudoElements = true;\r\n }\r\n\r\n /**\r\n * Returns the attached pseudo elements sorted by hydrogen count (ascending).\r\n *\r\n * @returns {Object} The sorted attached pseudo elements.\r\n */\r\n getAttachedPseudoElements() {\r\n let ordered = {};\r\n let that = this;\r\n\r\n Object.keys(this.attachedPseudoElements).sort().forEach(function (key) {\r\n ordered[key] = that.attachedPseudoElements[key];\r\n });\r\n\r\n return ordered;\r\n }\r\n\r\n /**\r\n * Returns the number of attached pseudo elements.\r\n *\r\n * @returns {Number} The number of attached pseudo elements.\r\n */\r\n getAttachedPseudoElementsCount() {\r\n return Object.keys(this.attachedPseudoElements).length;\r\n }\r\n\r\n /**\r\n * Returns whether this atom is a heteroatom (not C and not H).\r\n *\r\n * @returns {Boolean} A boolean indicating whether this atom is a heteroatom.\r\n */\r\n isHeteroAtom() {\r\n return this.element !== 'C' && this.element !== 'H';\r\n }\r\n\r\n /**\r\n * Defines this atom as the anchor for a ring. When doing repositionings of the vertices and the vertex associated with this atom is moved, the center of this ring is moved as well.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n addAnchoredRing(ringId) {\r\n if (!ArrayHelper.contains(this.anchoredRings, {\r\n value: ringId\r\n })) {\r\n this.anchoredRings.push(ringId);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of ringbonds (breaks in rings to generate the MST of the smiles) within this atom is connected to.\r\n *\r\n * @returns {Number} The number of ringbonds this atom is connected to.\r\n */\r\n getRingbondCount() {\r\n return this.ringbonds.length;\r\n }\r\n\r\n /**\r\n * Backs up the current rings.\r\n */\r\n backupRings() {\r\n this.originalRings = Array(this.rings.length);\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings[i] = this.rings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recent backed up rings.\r\n */\r\n restoreRings() {\r\n this.rings = Array(this.originalRings.length);\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings[i] = this.originalRings[i];\r\n }\r\n }\r\n\r\n /**\r\n * Checks whether or not two atoms share a common ringbond id. A ringbond is a break in a ring created when generating the spanning tree of a structure.\r\n *\r\n * @param {Atom} atomA An atom.\r\n * @param {Atom} atomB An atom.\r\n * @returns {Boolean} A boolean indicating whether or not two atoms share a common ringbond.\r\n */\r\n haveCommonRingbond(atomA, atomB) {\r\n for (let i = 0; i < atomA.ringbonds.length; i++) {\r\n for (let j = 0; j < atomB.ringbonds.length; j++) {\r\n if (atomA.ringbonds[i].id == atomB.ringbonds[j].id) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not the neighbouring elements of this atom equal the supplied array.\r\n * \r\n * @param {String[]} arr An array containing all the elements that are neighbouring this atom. E.g. ['C', 'O', 'O', 'N']\r\n * @returns {Boolean} A boolean indicating whether or not the neighbours match the supplied array of elements.\r\n */\r\n neighbouringElementsEqual(arr) {\r\n if (arr.length !== this.neighbouringElements.length) {\r\n return false;\r\n }\r\n\r\n arr.sort();\r\n this.neighbouringElements.sort();\r\n\r\n for (var i = 0; i < this.neighbouringElements.length; i++) {\r\n if (arr[i] !== this.neighbouringElements[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the atomic number of this atom.\r\n * \r\n * @returns {Number} The atomic number of this atom.\r\n */\r\n getAtomicNumber() {\r\n return Atom.atomicNumbers[this.element];\r\n }\r\n\r\n /**\r\n * Get the maximum number of bonds for this atom.\r\n * \r\n * @returns {Number} The maximum number of bonds of this atom.\r\n */\r\n getMaxBonds() {\r\n return Atom.maxBonds[this.element];\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to their maximum bonds.\r\n */\r\n static get maxBonds() {\r\n return {\r\n 'H': 1,\r\n 'C': 4,\r\n 'N': 3,\r\n 'O': 2,\r\n 'P': 3,\r\n 'S': 2,\r\n 'B': 3,\r\n 'F': 1,\r\n 'I': 1,\r\n 'Cl': 1,\r\n 'Br': 1\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic number.\r\n */\r\n static get atomicNumbers() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n\r\n /**\r\n * A map mapping element symbols to the atomic mass.\r\n */\r\n static get mass() {\r\n return {\r\n 'H': 1,\r\n 'He': 2,\r\n 'Li': 3,\r\n 'Be': 4,\r\n 'B': 5,\r\n 'b': 5,\r\n 'C': 6,\r\n 'c': 6,\r\n 'N': 7,\r\n 'n': 7,\r\n 'O': 8,\r\n 'o': 8,\r\n 'F': 9,\r\n 'Ne': 10,\r\n 'Na': 11,\r\n 'Mg': 12,\r\n 'Al': 13,\r\n 'Si': 14,\r\n 'P': 15,\r\n 'p': 15,\r\n 'S': 16,\r\n 's': 16,\r\n 'Cl': 17,\r\n 'Ar': 18,\r\n 'K': 19,\r\n 'Ca': 20,\r\n 'Sc': 21,\r\n 'Ti': 22,\r\n 'V': 23,\r\n 'Cr': 24,\r\n 'Mn': 25,\r\n 'Fe': 26,\r\n 'Co': 27,\r\n 'Ni': 28,\r\n 'Cu': 29,\r\n 'Zn': 30,\r\n 'Ga': 31,\r\n 'Ge': 32,\r\n 'As': 33,\r\n 'Se': 34,\r\n 'Br': 35,\r\n 'Kr': 36,\r\n 'Rb': 37,\r\n 'Sr': 38,\r\n 'Y': 39,\r\n 'Zr': 40,\r\n 'Nb': 41,\r\n 'Mo': 42,\r\n 'Tc': 43,\r\n 'Ru': 44,\r\n 'Rh': 45,\r\n 'Pd': 46,\r\n 'Ag': 47,\r\n 'Cd': 48,\r\n 'In': 49,\r\n 'Sn': 50,\r\n 'Sb': 51,\r\n 'Te': 52,\r\n 'I': 53,\r\n 'Xe': 54,\r\n 'Cs': 55,\r\n 'Ba': 56,\r\n 'La': 57,\r\n 'Ce': 58,\r\n 'Pr': 59,\r\n 'Nd': 60,\r\n 'Pm': 61,\r\n 'Sm': 62,\r\n 'Eu': 63,\r\n 'Gd': 64,\r\n 'Tb': 65,\r\n 'Dy': 66,\r\n 'Ho': 67,\r\n 'Er': 68,\r\n 'Tm': 69,\r\n 'Yb': 70,\r\n 'Lu': 71,\r\n 'Hf': 72,\r\n 'Ta': 73,\r\n 'W': 74,\r\n 'Re': 75,\r\n 'Os': 76,\r\n 'Ir': 77,\r\n 'Pt': 78,\r\n 'Au': 79,\r\n 'Hg': 80,\r\n 'Tl': 81,\r\n 'Pb': 82,\r\n 'Bi': 83,\r\n 'Po': 84,\r\n 'At': 85,\r\n 'Rn': 86,\r\n 'Fr': 87,\r\n 'Ra': 88,\r\n 'Ac': 89,\r\n 'Th': 90,\r\n 'Pa': 91,\r\n 'U': 92,\r\n 'Np': 93,\r\n 'Pu': 94,\r\n 'Am': 95,\r\n 'Cm': 96,\r\n 'Bk': 97,\r\n 'Cf': 98,\r\n 'Es': 99,\r\n 'Fm': 100,\r\n 'Md': 101,\r\n 'No': 102,\r\n 'Lr': 103,\r\n 'Rf': 104,\r\n 'Db': 105,\r\n 'Sg': 106,\r\n 'Bh': 107,\r\n 'Hs': 108,\r\n 'Mt': 109,\r\n 'Ds': 110,\r\n 'Rg': 111,\r\n 'Cn': 112,\r\n 'Uut': 113,\r\n 'Uuq': 114,\r\n 'Uup': 115,\r\n 'Uuh': 116,\r\n 'Uus': 117,\r\n 'Uuo': 118\r\n };\r\n }\r\n}\r\n\r\nmodule.exports = Atom;","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Ring = require('./Ring');\r\nconst { getChargeText } = require('./UtilityFunctions');\r\n\r\n/** \r\n * A class wrapping a canvas element.\r\n * \r\n * @property {HTMLElement} canvas The HTML element for the canvas associated with this CanvasWrapper instance.\r\n * @property {CanvasRenderingContext2D} ctx The CanvasRenderingContext2D of the canvas associated with this CanvasWrapper instance.\r\n * @property {Object} colors The colors object as defined in the SmilesDrawer options.\r\n * @property {Object} opts The SmilesDrawer options.\r\n * @property {Number} drawingWidth The width of the canvas.\r\n * @property {Number} drawingHeight The height of the canvas.\r\n * @property {Number} realWidth The width of the canvas real.\r\n * @property {Number} realHeight The height of the canvas real.\r\n * @property {Number} offsetX The horizontal offset required for centering the drawing.\r\n * @property {Number} offsetY The vertical offset required for centering the drawing.\r\n * @property {Number} fontLarge The large font size in pt.\r\n * @property {Number} fontSmall The small font size in pt.\r\n */\r\nclass CanvasWrapper {\r\n /**\r\n * The constructor for the class CanvasWrapper.\r\n *\r\n * @param {(String|HTMLElement)} target The canvas id or the canvas HTMLElement.\r\n * @param {ThemeManager} themeManager Theme manager for setting proper colors.\r\n * @param {Object} options The smiles drawer options object.\r\n */\r\n constructor(target, themeManager, options) {\r\n if (typeof target === 'string' || target instanceof String) {\r\n this.canvas = document.getElementById(target);\r\n } else {\r\n this.canvas = target;\r\n }\r\n\r\n this.ctx = this.canvas.getContext('2d');\r\n this.themeManager = themeManager;\r\n this.opts = options;\r\n this.drawingWidth = 0.0;\r\n this.drawingHeight = 0.0;\r\n this.realWidth = 0.0;\r\n this.realHeight = 0.0;\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n this.fontLarge = this.opts.fontSizeLarge + 'pt Helvetica, Arial, sans-serif';\r\n this.fontSmall = this.opts.fontSizeSmall + 'pt Helvetica, Arial, sans-serif';\r\n\r\n this.updateSize(this.opts.width, this.opts.height);\r\n\r\n this.ctx.font = this.fontLarge;\r\n this.hydrogenWidth = this.ctx.measureText('H').width;\r\n this.halfHydrogenWidth = this.hydrogenWidth / 2.0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // TODO: Find out why clear was here.\r\n // this.clear();\r\n }\r\n\r\n /**\r\n * Update the width and height of the canvas\r\n * \r\n * @param {Number} width \r\n * @param {Number} height \r\n */\r\n updateSize(width, height) {\r\n this.devicePixelRatio = window.devicePixelRatio || 1;\r\n this.backingStoreRatio = this.ctx.webkitBackingStorePixelRatio || this.ctx.mozBackingStorePixelRatio ||\r\n this.ctx.msBackingStorePixelRatio || this.ctx.oBackingStorePixelRatio ||\r\n this.ctx.backingStorePixelRatio || 1;\r\n this.ratio = this.devicePixelRatio / this.backingStoreRatio;\r\n\r\n this.canvas.width = width * this.ratio;\r\n this.canvas.height = height * this.ratio;\r\n if (this.ratio !== 1) {\r\n this.realWidth = width;\r\n this.realHeight = height;\r\n this.canvas.style.width = width + 'px';\r\n this.canvas.style.height = height + 'px';\r\n this.ctx.setTransform(this.ratio, 0, 0, this.ratio, 0, 0);\r\n }\r\n }\r\n\r\n /**\r\n * Sets a provided theme.\r\n *\r\n * @param {Object} theme A theme from the smiles drawer options.\r\n */\r\n setTheme(theme) {\r\n this.colors = theme;\r\n }\r\n\r\n /**\r\n * Scale the canvas based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n scale(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n var padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n var scaleX = this.canvas.offsetWidth / this.drawingWidth;\r\n var scaleY = this.canvas.offsetHeight / this.drawingHeight;\r\n\r\n var scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n\r\n this.ctx.scale(scale, scale);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.canvas.offsetHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.canvas.offsetWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Resets the transform of the canvas.\r\n */\r\n reset() {\r\n this.ctx.setTransform(1, 0, 0, 1, 0, 0);\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.colors) {\r\n return this.colors[key];\r\n }\r\n\r\n return this.colors['C'];\r\n }\r\n\r\n /**\r\n * Draws a circle to a canvas context.\r\n * @param {Number} x The x coordinate of the circles center.\r\n * @param {Number} y The y coordinate of the circles center.\r\n * @param {Number} radius The radius of the circle\r\n * @param {String} color A hex encoded color.\r\n * @param {Boolean} [fill=true] Whether to fill or stroke the circle.\r\n * @param {Boolean} [debug=false] Draw in debug mode.\r\n * @param {String} [debugText=''] A debug message.\r\n */\r\n drawCircle(x, y, radius, color, fill = true, debug = false, debugText = '') {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.lineWidth = 1.5;\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, radius, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n\r\n if (debug) {\r\n if (fill) {\r\n ctx.fillStyle = '#f00';\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = '#f00';\r\n ctx.stroke();\r\n }\r\n\r\n this.drawDebugText(x, y, debugText);\r\n } else {\r\n if (fill) {\r\n ctx.fillStyle = color;\r\n ctx.fill();\r\n } else {\r\n ctx.strokeStyle = color;\r\n ctx.stroke();\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a line to a canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} [dashed=false] Whether or not the line is dashed.\r\n * @param {Number} [alpha=1.0] The alpha value of the color.\r\n */\r\n drawLine(line, dashed = false, alpha = 1.0) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(4.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n // Draw the \"shadow\"\r\n if (!dashed) {\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness + 1.2;\r\n ctx.strokeStyle = this.themeManager.getColor('BACKGROUND');\r\n ctx.stroke();\r\n ctx.globalCompositeOperation = 'source-over';\r\n ctx.restore();\r\n }\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.moveTo(l.x, l.y);\r\n ctx.lineTo(r.x, r.y);\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n\r\n let gradient = this.ctx.createLinearGradient(l.x, l.y, r.x, r.y);\r\n if (line.isDecayPoint) {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(\"DECAY\"));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(\"DECAY\"));\r\n } else {\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n }\r\n\r\n if (dashed) {\r\n ctx.setLineDash([1, 1.5]);\r\n ctx.lineWidth = this.opts.bondThickness / 1.5;\r\n }\r\n\r\n if (alpha < 1.0) {\r\n ctx.globalAlpha = alpha;\r\n }\r\n\r\n ctx.strokeStyle = gradient;\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Number} width The wedge width.\r\n */\r\n drawWedge(line, width = 1.0) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // Add a shadow behind the line\r\n let shortLine = line.clone().shorten(5.0);\r\n\r\n let l = shortLine.getLeftVector().clone();\r\n let r = shortLine.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n l = line.getLeftVector().clone();\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l;\r\n let end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness));\r\n let u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness));\r\n let v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness));\r\n let w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(t.x, t.y);\r\n ctx.lineTo(u.x, u.y);\r\n ctx.lineTo(v.x, v.y);\r\n ctx.lineTo(w.x, w.y);\r\n\r\n let gradient = this.ctx.createRadialGradient(r.x, r.y, this.opts.bondLength, r.x, r.y, 0);\r\n gradient.addColorStop(0.4, this.themeManager.getColor(line.getLeftElement()) ||\r\n this.themeManager.getColor('C'));\r\n gradient.addColorStop(0.6, this.themeManager.getColor(line.getRightElement()) ||\r\n this.themeManager.getColor('C'));\r\n\r\n ctx.fillStyle = gradient;\r\n\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n let l = line.getLeftVector().clone();\r\n let r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n ctx.save();\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start;\r\n let end;\r\n let sStart;\r\n let sEnd;\r\n\r\n let shortLine = line.clone();\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n\r\n shortLine.shortenRight(1.0);\r\n\r\n sStart = shortLine.getRightVector().clone();\r\n sEnd = shortLine.getLeftVector().clone();\r\n } else {\r\n start = l;\r\n end = r;\r\n\r\n shortLine.shortenLeft(1.0);\r\n\r\n sStart = shortLine.getLeftVector().clone();\r\n sEnd = shortLine.getRightVector().clone();\r\n }\r\n\r\n sStart.x += offsetX;\r\n sStart.y += offsetY;\r\n sEnd.x += offsetX;\r\n sEnd.y += offsetY;\r\n\r\n let dir = Vector2.subtract(end, start).normalize();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineCap = 'round';\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n let length = line.getLength();\r\n let step = 1.25 / (length / (this.opts.bondThickness * 3.0));\r\n\r\n let changed = false;\r\n for (var t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length);\r\n let startDash = Vector2.add(start, to);\r\n let width = 1.5 * t;\r\n let dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n if (!changed && t > 0.5) {\r\n ctx.stroke();\r\n ctx.beginPath();\r\n ctx.strokeStyle = this.themeManager.getColor(line.getRightElement()) || this.themeManager.getColor('C');\r\n changed = true;\r\n }\r\n \r\n startDash.subtract(dashOffset);\r\n ctx.moveTo(startDash.x, startDash.y);\r\n startDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n ctx.lineTo(startDash.x, startDash.y);\r\n }\r\n\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.font = '5px Droid Sans, sans-serif';\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'top';\r\n ctx.fillStyle = '#ff0000';\r\n ctx.fillText(text, x + this.offsetX, y + this.offsetY);\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a ball to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ctx = this.ctx;\r\n\r\n ctx.save();\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, this.opts.bondLength / 4.5, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a point to the canvas.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, 1.5, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n ctx.beginPath();\r\n ctx.arc(x + this.offsetX, y + this.offsetY, 0.75, 0, MathHelper.twoPI, false);\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fill();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n ctx.save();\r\n\r\n ctx.textAlign = 'start';\r\n ctx.textBaseline = 'alphabetic';\r\n\r\n // Charge\r\n let chargeText = '';\r\n let chargeWidth = 0;\r\n\r\n if (charge) {\r\n chargeText = getChargeText(charge);\r\n\r\n ctx.font = this.fontSmall;\r\n chargeWidth = ctx.measureText(chargeText).width;\r\n }\r\n\r\n let isotopeText = '0';\r\n let isotopeWidth = 0;\r\n\r\n if (isotope > 0) {\r\n isotopeText = isotope.toString();\r\n ctx.font = this.fontSmall;\r\n isotopeWidth = ctx.measureText(isotopeText).width;\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') && \r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = { '0O': { element: 'O', count: 2, hydrogenCount: 0, previousElement: 'C', charge: '' } };\r\n charge = 0;\r\n }\r\n\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillStyle = this.themeManager.getColor('BACKGROUND');\r\n\r\n let dim = ctx.measureText(elementName);\r\n\r\n dim.totalWidth = dim.width + chargeWidth;\r\n dim.height = parseInt(this.fontLarge, 10);\r\n\r\n let r = (dim.width > this.opts.fontSizeLarge) ? dim.width : this.opts.fontSizeLarge;\r\n r /= 1.5;\r\n\r\n ctx.globalCompositeOperation = 'destination-out';\r\n ctx.beginPath();\r\n ctx.arc(x + offsetX, y + offsetY, r, 0, MathHelper.twoPI, true);\r\n ctx.closePath();\r\n ctx.fill();\r\n ctx.globalCompositeOperation = 'source-over';\r\n\r\n let cursorPos = -dim.width / 2.0;\r\n let cursorPosLeft = -dim.width / 2.0;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(elementName);\r\n ctx.fillText(elementName, x + offsetX + cursorPos, y + this.opts.halfFontSizeLarge + offsetY);\r\n cursorPos += dim.width;\r\n\r\n if (charge) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(chargeText, x + offsetX + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += chargeWidth;\r\n }\r\n\r\n if (isotope > 0) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(isotopeText, x + offsetX + cursorPosLeft - isotopeWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPosLeft -= isotopeWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hydrogenWidth = 0;\r\n let hydrogenCountWidth = 0;\r\n\r\n if (hydrogens === 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n cursorPosLeft -= hydrogenWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.fillText('H', hx, hy);\r\n\r\n cursorPos += hydrogenWidth;\r\n } else if (hydrogens > 1) {\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n hydrogenWidth = this.hydrogenWidth;\r\n ctx.font = this.fontSmall;\r\n hydrogenCountWidth = ctx.measureText(hydrogens).width;\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n\r\n if (direction === 'left') {\r\n hx += cursorPosLeft;\r\n } else if (direction === 'right') {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'down' && isTerminal) {\r\n hx += cursorPos;\r\n } else if (direction === 'up' && !isTerminal) {\r\n hy -= this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n } else if (direction === 'down' && !isTerminal) {\r\n hy += this.opts.fontSizeLarge + this.opts.quarterFontSizeLarge;\r\n hx -= this.halfHydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n ctx.fillText('H', hx, hy);\r\n\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogens, hx + this.halfHydrogenWidth + hydrogenCountWidth, hy + this.opts.fifthFontSizeSmall);\r\n\r\n cursorPos += hydrogenWidth + this.halfHydrogenWidth + hydrogenCountWidth;\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let openParenthesisWidth = 0;\r\n let closeParenthesisWidth = 0;\r\n\r\n let element = attachedPseudoElement[key].element;\r\n let elementCount = attachedPseudoElement[key].count;\r\n let hydrogenCount = attachedPseudoElement[key].hydrogenCount;\r\n let elementCharge = attachedPseudoElement[key].charge;\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n openParenthesisWidth = ctx.measureText('(').width;\r\n closeParenthesisWidth = ctx.measureText(')').width;\r\n }\r\n\r\n let elementWidth = ctx.measureText(element).width;\r\n let elementCountWidth = 0;\r\n\r\n let elementChargeText = '';\r\n let elementChargeWidth = 0;\r\n\r\n hydrogenWidth = 0;\r\n\r\n if (hydrogenCount > 0) {\r\n hydrogenWidth = this.hydrogenWidth;\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n elementCountWidth = ctx.measureText(elementCount).width;\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n elementChargeText = getChargeText(elementCharge);\r\n elementChargeWidth = ctx.measureText(elementChargeText).width;\r\n }\r\n\r\n hydrogenCountWidth = 0;\r\n\r\n if (hydrogenCount > 1) {\r\n hydrogenCountWidth = ctx.measureText(hydrogenCount).width;\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n let hx = x + offsetX;\r\n let hy = y + offsetY + this.opts.halfFontSizeLarge;\r\n\r\n ctx.fillStyle = this.themeManager.getColor(element);\r\n\r\n if (elementCount > 0) {\r\n cursorPosLeft -= elementCountWidth;\r\n }\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= closeParenthesisWidth;\r\n ctx.fillText(')', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText('(', hx + cursorPos, hy);\r\n cursorPos += openParenthesisWidth;\r\n }\r\n }\r\n\r\n if (direction === 'left') {\r\n cursorPosLeft -= elementWidth;\r\n ctx.fillText(element, hx + cursorPosLeft, hy)\r\n } else {\r\n ctx.fillText(element, hx + cursorPos, hy);\r\n cursorPos += elementWidth;\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= hydrogenWidth + hydrogenCountWidth;\r\n ctx.fillText('H', hx + cursorPosLeft, hy);\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPosLeft + hydrogenWidth, hy + this.opts.fifthFontSizeSmall);\r\n }\r\n } else {\r\n ctx.fillText('H', hx + cursorPos, hy);\r\n cursorPos += hydrogenWidth;\r\n\r\n if (hydrogenCount > 1) {\r\n ctx.font = this.fontSmall;\r\n ctx.fillText(hydrogenCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += hydrogenCountWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.font = this.fontLarge;\r\n\r\n if (elementCount > 1 && hydrogenCount > 0) {\r\n if (direction === 'left') {\r\n cursorPosLeft -= openParenthesisWidth;\r\n ctx.fillText('(', hx + cursorPosLeft, hy);\r\n } else {\r\n ctx.fillText(')', hx + cursorPos, hy);\r\n cursorPos += closeParenthesisWidth;\r\n }\r\n }\r\n\r\n ctx.font = this.fontSmall;\r\n\r\n if (elementCount > 1) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementCount, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, hy + this.opts.fifthFontSizeSmall);\r\n } else {\r\n ctx.fillText(elementCount, hx + cursorPos, hy + this.opts.fifthFontSizeSmall);\r\n cursorPos += elementCountWidth;\r\n }\r\n }\r\n\r\n if (elementCharge !== 0) {\r\n if (direction === 'left') {\r\n ctx.fillText(elementChargeText, hx + cursorPosLeft +\r\n openParenthesisWidth + closeParenthesisWidth + hydrogenWidth +\r\n hydrogenCountWidth + elementWidth, y - this.opts.fifthFontSizeSmall + offsetY);\r\n } else {\r\n ctx.fillText(elementChargeText, hx + cursorPos, y - this.opts.fifthFontSizeSmall + offsetY);\r\n cursorPos += elementChargeWidth;\r\n }\r\n }\r\n }\r\n\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\n getChargeText(charge) {\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n }\r\n\r\n /**\r\n * Draws a dubug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n this.drawCircle(x, y, 2, color, true, true, debugText);\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.themeManager.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Clear the canvas.\r\n *\r\n */\r\n clear() {\r\n this.ctx.clearRect(0, 0, this.canvas.offsetWidth, this.canvas.offsetHeight);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = CanvasWrapper;","//@ts-check\r\n\r\nclass DecayPoint {\r\n\r\n /**\r\n * Enum values for Decay points\r\n * ALL use all variants of decay points\r\n * COO -CO-O- type of decay\r\n * CONH -CO-NH- type of decay\r\n * @return {{ALL: number, COO: number, CONH: number}}\r\n */\r\n static get VALUES() {\r\n return { ALL: 0, COO: 1, CONH: 2 };\r\n }\r\n}\r\n\r\nmodule.exports = DecayPoint;\r\n","//@ts-check\r\n\r\nclass DecayState {\r\n\r\n static get VALUES() {\r\n return { NO: 0, STANDARD: 1, SOURCE: 2, STANDARD_AND_SOURCE: 3};\r\n }\r\n}\r\n\r\nmodule.exports = DecayState;\r\n","\r\nclass Direction {\r\n\r\n static get VALUES() {\r\n return { N: 0, POLYKETIDE: 1, C: 2 };\r\n }\r\n\r\n static getProperValue(isPolyketide, vertexElement, vertexId, firstVertexId) {\r\n if (isPolyketide) {\r\n return this.VALUES.POLYKETIDE;\r\n }\r\n if (vertexElement === \"C\" && vertexId !== firstVertexId) {\r\n return this.VALUES.C;\r\n }\r\n return this.VALUES.N;\r\n }\r\n\r\n}\r\n\r\nmodule.exports= Direction;\r\n","//@ts-check\r\nconst MathHelper = require('./MathHelper');\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Line = require('./Line');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Atom = require('./Atom');\r\nconst Ring = require('./Ring');\r\nconst RingConnection = require('./RingConnection');\r\nconst CanvasWrapper = require('./CanvasWrapper');\r\nconst Graph = require('./Graph');\r\nconst SSSR = require('./SSSR');\r\nconst DecayState = require('./DecayState');\r\nconst ThemeManager = require('./ThemeManager');\r\n\r\n/**\r\n * The main class of the application representing the smiles drawer\r\n *\r\n * @property {Graph} graph The graph associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} ringIdCounter An internal counter to keep track of ring ids.\r\n * @property {Number} ringConnectionIdCounter An internal counter to keep track of ring connection ids.\r\n * @property {CanvasWrapper} canvasWrapper The CanvasWrapper associated with this SmilesDrawer.Drawer instance.\r\n * @property {Number} totalOverlapScore The current internal total overlap score.\r\n * @property {Object} defaultOptions The default options.\r\n * @property {Object} opts The merged options.\r\n * @property {Object} theme The current theme.\r\n */\r\nclass Drawer {\r\n /**\r\n * The constructor for the class SmilesDrawer.\r\n *\r\n * @param {Object} options An object containing custom values for different options. It is merged with the default options.\r\n */\r\n constructor(options) {\r\n this.graph = null;\r\n this.doubleBondConfigCount = 0;\r\n this.doubleBondConfig = null;\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n this.canvasWrapper = null;\r\n this.totalOverlapScore = 0;\r\n\r\n this.defaultOptions = {\r\n width: 500,\r\n height: 500,\r\n offsetX: 0, /* offsetX offset of canvas in page X. Typically canvas.offsetLeft */\r\n offsetY: 0, /* offsetY offset of canvas in page Y. Typically canvas.offsetTop */\r\n bondThickness: 0.6,\r\n bondLength: 15,\r\n shortBondLength: 0.85,\r\n bondSpacing: 0.18 * 15,\r\n atomVisualization: 'default',\r\n isomeric: true,\r\n debug: false,\r\n terminalCarbons: false,\r\n explicitHydrogens: false,\r\n overlapSensitivity: 0.42,\r\n overlapResolutionIterations: 1,\r\n compactDrawing: true,\r\n fontSizeLarge: 5,\r\n fontSizeSmall: 3,\r\n padding: 20.0,\r\n experimentalSSSR: false,\r\n kkThreshold: 0.1,\r\n kkInnerThreshold: 0.1,\r\n kkMaxIteration: 20000,\r\n kkMaxInnerIteration: 50,\r\n kkMaxEnergy: 1e9,\r\n drawDecayPoints: DecayState.VALUES.NO,\r\n decaySource: [],\r\n mouseTolerance: 3,\r\n themes: {\r\n dark: {\r\n C: '#fff',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#fff',\r\n BACKGROUND: '#141414',\r\n DECAY: '#027c21'\r\n },\r\n light: {\r\n C: '#222',\r\n O: '#e74c3c',\r\n N: '#3498db',\r\n F: '#27ae60',\r\n CL: '#16a085',\r\n BR: '#d35400',\r\n I: '#8e44ad',\r\n P: '#d35400',\r\n S: '#f1c40f',\r\n B: '#e67e22',\r\n SI: '#e67e22',\r\n H: '#222',\r\n BACKGROUND: '#fff',\r\n DECAY: '#027c21'\r\n }\r\n }\r\n };\r\n\r\n this.opts = this.extend(true, this.defaultOptions, options);\r\n this.opts.halfBondSpacing = this.opts.bondSpacing / 2.0;\r\n this.opts.bondLengthSq = this.opts.bondLength * this.opts.bondLength;\r\n this.opts.halfFontSizeLarge = this.opts.fontSizeLarge / 2.0;\r\n this.opts.quarterFontSizeLarge = this.opts.fontSizeLarge / 4.0;\r\n this.opts.fifthFontSizeSmall = this.opts.fontSizeSmall / 5.0;\r\n\r\n // Set the default theme.\r\n this.theme = this.opts.themes.dark;\r\n\r\n this.drawDecayPoints = this.opts.drawDecayPoints;\r\n }\r\n\r\n /**\r\n * A helper method to extend the default options with user supplied ones.\r\n */\r\n extend() {\r\n let that = this;\r\n let extended = {};\r\n let deep = false;\r\n let i = 0;\r\n let length = arguments.length;\r\n\r\n if (Object.prototype.toString.call(arguments[0]) === '[object Boolean]') {\r\n deep = arguments[0];\r\n i++;\r\n }\r\n\r\n let merge = function (obj) {\r\n for (var prop in obj) {\r\n if (Object.prototype.hasOwnProperty.call(obj, prop)) {\r\n if (deep && Object.prototype.toString.call(obj[prop]) === '[object Object]') {\r\n extended[prop] = that.extend(true, extended[prop], obj[prop]);\r\n } else {\r\n extended[prop] = obj[prop];\r\n }\r\n }\r\n }\r\n };\r\n\r\n for (; i < length; i++) {\r\n let obj = arguments[i];\r\n merge(obj);\r\n }\r\n\r\n return extended;\r\n }\r\n\r\n /**\r\n * Is setup to draw decay points?\r\n * when boolean this.drawDecayPoint is true then return isDecay\r\n * @param isDecay bool - edge.isDecay\r\n * @returns {Boolean}\r\n */\r\n isDrawDecayPoint(isDecay) {\r\n return this.drawDecayPoints !== DecayState.VALUES.NO && isDecay;\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to a canvas element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML canvas element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n this.initDraw(data, themeName, infoOnly);\r\n\r\n if (!this.infoOnly) {\r\n this.themeManager = new ThemeManager(this.opts.themes, themeName);\r\n this.canvasWrapper = new CanvasWrapper(target, this.themeManager, this.opts);\r\n }\r\n\r\n if (!infoOnly) {\r\n this.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n\r\n if (this.opts.debug) {\r\n console.log(this.graph);\r\n console.log(this.rings);\r\n console.log(this.ringConnections);\r\n }\r\n }\r\n }\r\n\r\n clear() {\r\n if (this.canvasWrapper) {\r\n this.canvasWrapper.clear();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the number of rings this edge is a part of.\r\n *\r\n * @param {Number} edgeId The id of an edge.\r\n * @returns {Number} The number of rings the provided edge is part of.\r\n */\r\n edgeRingCount(edgeId) {\r\n let edge = this.graph.edges[edgeId];\r\n let a = this.graph.vertices[edge.sourceId];\r\n let b = this.graph.vertices[edge.targetId];\r\n\r\n return Math.min(a.value.rings.length, b.value.rings.length);\r\n }\r\n\r\n /**\r\n * Returns an array containing the bridged rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all bridged rings associated with this molecule.\r\n */\r\n getBridgedRings() {\r\n let bridgedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n bridgedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return bridgedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all fused rings associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all fused rings associated with this molecule.\r\n */\r\n getFusedRings() {\r\n let fusedRings = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isFused) {\r\n fusedRings.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return fusedRings;\r\n }\r\n\r\n /**\r\n * Returns an array containing all spiros associated with this molecule.\r\n *\r\n * @returns {Ring[]} An array containing all spiros associated with this molecule.\r\n */\r\n getSpiros() {\r\n let spiros = Array();\r\n\r\n for (var i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isSpiro) {\r\n spiros.push(this.rings[i]);\r\n }\r\n }\r\n\r\n return spiros;\r\n }\r\n\r\n /**\r\n * Returns a string containing a semicolon and new-line separated list of ring properties: Id; Members Count; Neighbours Count; IsSpiro; IsFused; IsBridged; Ring Count (subrings of bridged rings)\r\n *\r\n * @returns {String} A string as described in the method description.\r\n */\r\n printRingInfo() {\r\n let result = '';\r\n for (let i = 0; i < this.rings.length; i++) {\r\n const ring = this.rings[i];\r\n\r\n result += ring.id + ';';\r\n result += ring.members.length + ';';\r\n result += ring.neighbours.length + ';';\r\n result += ring.isSpiro ? 'true;' : 'false;';\r\n result += ring.isFused ? 'true;' : 'false;';\r\n result += ring.isBridged ? 'true;' : 'false;';\r\n result += ring.rings.length + ';';\r\n result += '\\n';\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Rotates the drawing to make the widest dimension horizontal.\r\n */\r\n rotateDrawing() {\r\n // Rotate the vertices to make the molecule align horizontally\r\n // Find the longest distance\r\n let a = 0;\r\n let b = 0;\r\n let maxDist = 0;\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertexA = this.graph.vertices[i];\r\n\r\n if (!vertexA.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n for (let j = i + 1; j < this.graph.vertices.length; j++) {\r\n let vertexB = this.graph.vertices[j];\r\n\r\n if (!vertexB.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = vertexA.position.distanceSq(vertexB.position);\r\n\r\n if (dist > maxDist) {\r\n maxDist = dist;\r\n a = i;\r\n b = j;\r\n }\r\n }\r\n }\r\n\r\n let angle = -Vector2.subtract(this.graph.vertices[a].position, this.graph.vertices[b].position).angle();\r\n\r\n if (!isNaN(angle)) {\r\n // Round to 30 degrees\r\n let remainder = angle % 0.523599;\r\n\r\n // Round either up or down in 30 degree steps\r\n if (remainder < 0.2617995) {\r\n angle = angle - remainder;\r\n } else {\r\n angle += 0.523599 - remainder;\r\n }\r\n\r\n // Finally, rotate everything\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (i === b) {\r\n continue;\r\n }\r\n\r\n this.graph.vertices[i].position.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.rings[i].center.rotateAround(angle, this.graph.vertices[b].position);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.totalOverlapScore;\r\n }\r\n\r\n /**\r\n * Returns the ring count of the current molecule.\r\n *\r\n * @returns {Number} The ring count.\r\n */\r\n getRingCount() {\r\n return this.rings.length;\r\n }\r\n\r\n /**\r\n * Checks whether or not the current molecule a bridged ring.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not the current molecule a bridged ring.\r\n */\r\n hasBridgedRing() {\r\n return this.bridgedRing;\r\n }\r\n\r\n /**\r\n * Returns the number of heavy atoms (non-hydrogen) in the current molecule.\r\n *\r\n * @returns {Number} The heavy atom count.\r\n */\r\n getHeavyAtomCount() {\r\n let hac = 0;\r\n\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.element !== 'H') {\r\n hac++;\r\n }\r\n }\r\n\r\n return hac;\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n let molecularFormula = '';\r\n let counts = new Map();\r\n\r\n // Initialize element count\r\n for (var i = 0; i < this.graph.vertices.length; i++) {\r\n let atom = this.graph.vertices[i].value;\r\n\r\n if (counts.has(atom.element)) {\r\n counts.set(atom.element, counts.get(atom.element) + 1);\r\n } else {\r\n counts.set(atom.element, 1);\r\n }\r\n\r\n // Hydrogens attached to a chiral center were added as vertices,\r\n // those in non chiral brackets are added here\r\n if (atom.bracket && !atom.bracket.chirality) {\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + atom.bracket.hcount);\r\n } else {\r\n counts.set('H', atom.bracket.hcount);\r\n }\r\n }\r\n\r\n // Add the implicit hydrogens according to valency, exclude\r\n // bracket atoms as they were handled and always have the number\r\n // of hydrogens specified explicitly\r\n if (!atom.bracket) {\r\n let nHydrogens = Atom.maxBonds[atom.element] - atom.bondCount;\r\n\r\n if (atom.isPartOfAromaticRing) {\r\n nHydrogens--;\r\n }\r\n\r\n if (counts.has('H')) {\r\n counts.set('H', counts.get('H') + nHydrogens);\r\n } else {\r\n counts.set('H', nHydrogens);\r\n }\r\n }\r\n }\r\n\r\n if (counts.has('C')) {\r\n let count = counts.get('C');\r\n molecularFormula += 'C' + (count > 1 ? count : '');\r\n counts.delete('C');\r\n }\r\n\r\n if (counts.has('H')) {\r\n let count = counts.get('H');\r\n molecularFormula += 'H' + (count > 1 ? count : '');\r\n counts.delete('H');\r\n }\r\n\r\n let elements = Object.keys(Atom.atomicNumbers).sort();\r\n\r\n elements.map(e => {\r\n if (counts.has(e)) {\r\n let count = counts.get(e);\r\n molecularFormula += e + (count > 1 ? count : '');\r\n }\r\n });\r\n\r\n return molecularFormula;\r\n }\r\n\r\n /**\r\n * Returns the type of the ringbond (e.g. '=' for a double bond). The ringbond represents the break in a ring introduced when creating the MST. If the two vertices supplied as arguments are not part of a common ringbond, the method returns null.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(String|null)} Returns the ringbond type or null, if the two supplied vertices are not connected by a ringbond.\r\n */\r\n getRingbondType(vertexA, vertexB) {\r\n // Checks whether the two vertices are the ones connecting the ring\r\n // and what the bond type should be.\r\n if (vertexA.value.getRingbondCount() < 1 || vertexB.value.getRingbondCount() < 1) {\r\n return null;\r\n }\r\n\r\n for (var i = 0; i < vertexA.value.ringbonds.length; i++) {\r\n for (var j = 0; j < vertexB.value.ringbonds.length; j++) {\r\n // if(i != j) continue;\r\n if (vertexA.value.ringbonds[i].id === vertexB.value.ringbonds[j].id) {\r\n // If the bonds are equal, it doesn't matter which bond is returned.\r\n // if they are not equal, return the one that is not the default (\"-\")\r\n if (vertexA.value.ringbonds[i].bondType === '-') {\r\n return vertexB.value.ringbonds[j].bond;\r\n } else {\r\n return vertexA.value.ringbonds[i].bond;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n initDraw(data, themeName, infoOnly) {\r\n this.data = data;\r\n this.infoOnly = infoOnly;\r\n\r\n this.ringIdCounter = 0;\r\n this.ringConnectionIdCounter = 0;\r\n\r\n this.graph = new Graph(data, this.opts.isomeric, this.opts);\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n this.bridgedRing = false;\r\n\r\n // Reset those, in case the previous drawn SMILES had a dangling \\ or /\r\n this.doubleBondConfigCount = null;\r\n this.doubleBondConfig = null;\r\n\r\n this.initRings();\r\n this.initHydrogens();\r\n this.graph.findDecayPoints();\r\n }\r\n\r\n processGraph() {\r\n this.position();\r\n\r\n // Restore the ring information (removes bridged rings and replaces them with the original, multiple, rings)\r\n this.restoreRingInformation();\r\n\r\n // Atoms bonded to the same ring atom\r\n this.resolvePrimaryOverlaps();\r\n\r\n let overlapScore = this.getOverlapScore();\r\n\r\n this.totalOverlapScore = this.getOverlapScore().total;\r\n\r\n for (var o = 0; o < this.opts.overlapResolutionIterations; o++) {\r\n for (var i = 0; i < this.graph.edges.length; i++) {\r\n let edge = this.graph.edges[i];\r\n if (this.isEdgeRotatable(edge)) {\r\n let subTreeDepthA = this.graph.getTreeDepth(edge.sourceId, edge.targetId);\r\n let subTreeDepthB = this.graph.getTreeDepth(edge.targetId, edge.sourceId);\r\n\r\n // Only rotate the shorter subtree\r\n let a = edge.targetId;\r\n let b = edge.sourceId;\r\n\r\n if (subTreeDepthA > subTreeDepthB) {\r\n a = edge.sourceId;\r\n b = edge.targetId;\r\n }\r\n\r\n let subTreeOverlap = this.getSubtreeOverlapScore(b, a, overlapScore.vertexScores);\r\n if (subTreeOverlap.value > this.opts.overlapSensitivity) {\r\n let vertexA = this.graph.vertices[a];\r\n let vertexB = this.graph.vertices[b];\r\n let neighboursB = vertexB.getNeighbours(a);\r\n\r\n if (neighboursB.length === 1) {\r\n let neighbour = this.graph.vertices[neighboursB[0]];\r\n let angle = neighbour.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbour.id, vertexB.id, angle, vertexB.position);\r\n // If the new overlap is bigger, undo change\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbour.id, vertexB.id, -angle, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n } else if (neighboursB.length === 2) {\r\n // Switch places / sides\r\n // If vertex a is in a ring, do nothing\r\n if (vertexB.value.rings.length !== 0 && vertexA.value.rings.length !== 0) {\r\n continue;\r\n }\r\n\r\n let neighbourA = this.graph.vertices[neighboursB[0]];\r\n let neighbourB = this.graph.vertices[neighboursB[1]];\r\n\r\n if (neighbourA.value.rings.length === 1 && neighbourB.value.rings.length === 1) {\r\n // Both neighbours in same ring. TODO: does this create problems with wedges? (up = down and vice versa?)\r\n if (neighbourA.value.rings[0] !== neighbourB.value.rings[0]) {\r\n continue;\r\n }\r\n // TODO: Rotate circle\r\n } else if (neighbourA.value.rings.length !== 0 || neighbourB.value.rings.length !== 0) {\r\n continue;\r\n } else {\r\n let angleA = neighbourA.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n let angleB = neighbourB.position.getRotateAwayFromAngle(vertexA.position, vertexB.position, MathHelper.toRad(120));\r\n\r\n this.rotateSubtree(neighbourA.id, vertexB.id, angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, angleB, vertexB.position);\r\n\r\n let newTotalOverlapScore = this.getOverlapScore().total;\r\n\r\n if (newTotalOverlapScore > this.totalOverlapScore) {\r\n this.rotateSubtree(neighbourA.id, vertexB.id, -angleA, vertexB.position);\r\n this.rotateSubtree(neighbourB.id, vertexB.id, -angleB, vertexB.position);\r\n } else {\r\n this.totalOverlapScore = newTotalOverlapScore;\r\n }\r\n }\r\n }\r\n\r\n overlapScore = this.getOverlapScore();\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.resolveSecondaryOverlaps(overlapScore.scores);\r\n\r\n if (this.opts.isomeric) {\r\n this.annotateStereochemistry();\r\n }\r\n\r\n // Initialize pseudo elements or shortcuts\r\n if (this.opts.compactDrawing && this.opts.atomVisualization === 'default') {\r\n this.initPseudoElements();\r\n }\r\n\r\n this.rotateDrawing();\r\n }\r\n\r\n /**\r\n * Initializes rings and ringbonds for the current molecule.\r\n */\r\n initRings() {\r\n let openBonds = new Map();\r\n\r\n // Close the open ring bonds (spanning tree -> graph)\r\n for (let i = this.graph.vertices.length - 1; i >= 0; i--) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.ringbonds.length === 0) {\r\n continue;\r\n }\r\n\r\n for (let j = 0; j < vertex.value.ringbonds.length; j++) {\r\n let ringbondId = vertex.value.ringbonds[j].id;\r\n let ringbondBond = vertex.value.ringbonds[j].bond;\r\n\r\n // If the other ringbond id has not been discovered,\r\n // add it to the open bonds map and continue.\r\n // if the other ringbond id has already been discovered,\r\n // create a bond between the two atoms.\r\n if (!openBonds.has(ringbondId)) {\r\n openBonds.set(ringbondId, [vertex.id, ringbondBond]);\r\n } else {\r\n let sourceVertexId = vertex.id;\r\n let targetVertexId = openBonds.get(ringbondId)[0];\r\n let targetRingbondBond = openBonds.get(ringbondId)[1];\r\n let edge = new Edge(sourceVertexId, targetVertexId, 1);\r\n edge.setBondType(targetRingbondBond || ringbondBond || '-');\r\n let edgeId = this.graph.addEdge(edge);\r\n let targetVertex = this.graph.vertices[targetVertexId];\r\n\r\n vertex.addRingbondChild(targetVertexId, j);\r\n vertex.value.addNeighbouringElement(targetVertex.value.element);\r\n targetVertex.addRingbondChild(sourceVertexId, j);\r\n targetVertex.value.addNeighbouringElement(vertex.value.element);\r\n vertex.edges.push(edgeId);\r\n targetVertex.edges.push(edgeId);\r\n\r\n openBonds.delete(ringbondId);\r\n }\r\n }\r\n }\r\n\r\n // Get the rings in the graph (the SSSR)\r\n let rings = SSSR.getRings(this.graph, this.opts.experimentalSSSR);\r\n\r\n if (rings === null) {\r\n return;\r\n }\r\n\r\n for (let i = 0; i < rings.length; i++) {\r\n let ringVertices = [...rings[i]];\r\n let ringId = this.addRing(new Ring(ringVertices));\r\n\r\n // Add the ring to the atoms\r\n for (let j = 0; j < ringVertices.length; j++) {\r\n this.graph.vertices[ringVertices[j]].value.rings.push(ringId);\r\n }\r\n }\r\n\r\n // Find connection between rings\r\n // Check for common vertices and create ring connections. This is a bit\r\n // ugly, but the ringcount is always fairly low (< 100)\r\n for (let i = 0; i < this.rings.length - 1; i++) {\r\n for (let j = i + 1; j < this.rings.length; j++) {\r\n let a = this.rings[i];\r\n let b = this.rings[j];\r\n let ringConnection = new RingConnection(a, b);\r\n\r\n // If there are no vertices in the ring connection, then there\r\n // is no ring connection\r\n if (ringConnection.vertices.size > 0) {\r\n this.addRingConnection(ringConnection);\r\n }\r\n }\r\n }\r\n\r\n // Add neighbours to the rings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n ring.neighbours = RingConnection.getNeighbours(this.ringConnections, ring.id);\r\n }\r\n\r\n // Anchor the ring to one of it's members, so that the ring center will always\r\n // be tied to a single vertex when doing repositionings\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n this.graph.vertices[ring.members[0]].value.addAnchoredRing(ring.id);\r\n }\r\n\r\n // Backup the ring information to restore after placing the bridged ring.\r\n // This is needed in order to identify aromatic rings and stuff like this in\r\n // rings that are member of the superring.\r\n this.backupRingInformation();\r\n\r\n\r\n // Replace rings contained by a larger bridged ring with a bridged ring\r\n while (this.rings.length > 0) {\r\n let id = -1;\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isPartOfBridgedRing(ring.id) && !ring.isBridged) {\r\n id = ring.id;\r\n }\r\n }\r\n\r\n if (id === -1) {\r\n break;\r\n }\r\n\r\n let ring = this.getRing(id);\r\n\r\n let involvedRings = this.getBridgedRingRings(ring.id);\r\n\r\n this.bridgedRing = true;\r\n this.createBridgedRing(involvedRings, ring.members[0]);\r\n\r\n // Remove the rings\r\n for (let i = 0; i < involvedRings.length; i++) {\r\n this.removeRing(involvedRings[i]);\r\n }\r\n }\r\n }\r\n\r\n initHydrogens() {\r\n // Do not draw hydrogens except when they are connected to a stereocenter connected to two or more rings.\r\n if (!this.opts.explicitHydrogens) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.value.element !== 'H') {\r\n continue;\r\n }\r\n\r\n // Hydrogens should have only one neighbour, so just take the first\r\n // Also set hasHydrogen true on connected atom\r\n let neighbour = this.graph.vertices[vertex.neighbours[0]];\r\n neighbour.value.hasHydrogen = true;\r\n\r\n if (!neighbour.value.isStereoCenter || neighbour.value.rings.length < 2 && !neighbour.value.bridgedRing ||\r\n neighbour.value.bridgedRing && neighbour.value.originalRings.length < 2) {\r\n vertex.value.isDrawn = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns all rings connected by bridged bonds starting from the ring with the supplied ring id.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array containing all ring ids of rings part of a bridged ring system.\r\n */\r\n getBridgedRingRings(ringId) {\r\n let involvedRings = Array();\r\n let that = this;\r\n\r\n let recurse = function (r) {\r\n let ring = that.getRing(r);\r\n\r\n involvedRings.push(r);\r\n\r\n for (let i = 0; i < ring.neighbours.length; i++) {\r\n let n = ring.neighbours[i];\r\n\r\n if (involvedRings.indexOf(n) === -1 &&\r\n n !== r &&\r\n RingConnection.isBridge(that.ringConnections, that.graph.vertices, r, n)) {\r\n recurse(n);\r\n }\r\n }\r\n };\r\n\r\n recurse(ringId);\r\n\r\n return ArrayHelper.unique(involvedRings);\r\n }\r\n\r\n /**\r\n * Checks whether or not a ring is part of a bridged ring.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not the supplied ring (by id) is part of a bridged ring system.\r\n */\r\n isPartOfBridgedRing(ringId) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].containsRing(ringId) &&\r\n this.ringConnections[i].isBridge(this.graph.vertices)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Creates a bridged ring.\r\n *\r\n * @param {Number[]} ringIds An array of ids of rings involved in the bridged ring.\r\n * @param {Number} sourceVertexId The vertex id to start the bridged ring discovery from.\r\n * @returns {Ring} The bridged ring.\r\n */\r\n createBridgedRing(ringIds, sourceVertexId) {\r\n let ringMembers = new Set();\r\n let vertices = new Set();\r\n let neighbours = new Set();\r\n\r\n for (let i = 0; i < ringIds.length; i++) {\r\n let ring = this.getRing(ringIds[i]);\r\n ring.isPartOfBridged = true;\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n vertices.add(ring.members[j]);\r\n }\r\n\r\n for (let j = 0; j < ring.neighbours.length; j++) {\r\n let id = ring.neighbours[j];\r\n\r\n if (ringIds.indexOf(id) === -1) {\r\n neighbours.add(ring.neighbours[j]);\r\n }\r\n }\r\n }\r\n\r\n // A vertex is part of the bridged ring if it only belongs to\r\n // one of the rings (or to another ring\r\n // which is not part of the bridged ring).\r\n let leftovers = new Set();\r\n\r\n for (let id of vertices) {\r\n let vertex = this.graph.vertices[id];\r\n let intersection = ArrayHelper.intersection(ringIds, vertex.value.rings);\r\n\r\n if (vertex.value.rings.length === 1 || intersection.length === 1) {\r\n ringMembers.add(vertex.id);\r\n } else {\r\n leftovers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Vertices can also be part of multiple rings and lay on the bridged ring,\r\n // however, they have to have at least two neighbours that are not part of\r\n // two rings\r\n let insideRing = Array();\r\n for (let id of leftovers) {\r\n let vertex = this.graph.vertices[id];\r\n let onRing = false;\r\n\r\n for (let j = 0; j < vertex.edges.length; j++) {\r\n if (this.edgeRingCount(vertex.edges[j]) === 1) {\r\n onRing = true;\r\n }\r\n }\r\n\r\n if (onRing) {\r\n vertex.value.isBridgeNode = true;\r\n ringMembers.add(vertex.id);\r\n } else {\r\n vertex.value.isBridge = true;\r\n ringMembers.add(vertex.id);\r\n }\r\n }\r\n\r\n // Create the ring\r\n let ring = new Ring([...ringMembers]);\r\n this.addRing(ring);\r\n\r\n ring.isBridged = true;\r\n ring.neighbours = [...neighbours];\r\n for (let i = 0; i < ringIds.length; i++) {\r\n ring.rings.push(this.getRing(ringIds[i]).clone());\r\n }\r\n\r\n for (let i = 0; i < ring.members.length; i++) {\r\n this.graph.vertices[ring.members[i]].value.bridgedRing = ring.id;\r\n }\r\n\r\n // Atoms inside the ring are no longer part of a ring but are now\r\n // associated with the bridged ring\r\n for (let i = 0; i < insideRing.length; i++) {\r\n let vertex = this.graph.vertices[insideRing[i]];\r\n vertex.value.rings = Array();\r\n }\r\n\r\n // Remove former rings from members of the bridged ring and add the bridged ring\r\n for (let id of ringMembers) {\r\n let vertex = this.graph.vertices[id];\r\n vertex.value.rings = ArrayHelper.removeAll(vertex.value.rings, ringIds);\r\n vertex.value.rings.push(ring.id);\r\n }\r\n\r\n // Remove all the ring connections no longer used\r\n for (let i = 0; i < ringIds.length; i++) {\r\n for (let j = i + 1; j < ringIds.length; j++) {\r\n this.removeRingConnectionsBetween(ringIds[i], ringIds[j]);\r\n }\r\n }\r\n\r\n // Update the ring connections and add this ring to the neighbours neighbours\r\n for (let id of neighbours) {\r\n let connections = this.getRingConnections(id, ringIds);\r\n\r\n for (let j = 0; j < connections.length; j++) {\r\n this.getRingConnection(connections[j]).updateOther(ring.id, id);\r\n }\r\n\r\n this.getRing(id).neighbours.push(ring.id);\r\n }\r\n\r\n return ring;\r\n }\r\n\r\n /**\r\n * Checks whether or not two vertices are in the same ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices are in the same ring.\r\n */\r\n areVerticesInSameRing(vertexA, vertexB) {\r\n // This is a little bit lighter (without the array and push) than\r\n // getCommonRings().length > 0\r\n for (let i = 0; i < vertexA.value.rings.length; i++) {\r\n for (let j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] === vertexB.value.rings[j]) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Returns an array of ring ids shared by both vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {Number[]} An array of ids of rings shared by the two vertices.\r\n */\r\n getCommonRings(vertexA, vertexB) {\r\n let commonRings = Array();\r\n\r\n for (var i = 0; i < vertexA.value.rings.length; i++) {\r\n for (var j = 0; j < vertexB.value.rings.length; j++) {\r\n if (vertexA.value.rings[i] == vertexB.value.rings[j]) {\r\n commonRings.push(vertexA.value.rings[i]);\r\n }\r\n }\r\n }\r\n\r\n return commonRings;\r\n }\r\n\r\n /**\r\n * Returns the aromatic or largest ring shared by the two vertices.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @returns {(Ring|null)} If an aromatic common ring exists, that ring, else the largest (non-aromatic) ring, else null.\r\n */\r\n getLargestOrAromaticCommonRing(vertexA, vertexB) {\r\n let commonRings = this.getCommonRings(vertexA, vertexB);\r\n let maxSize = 0;\r\n let largestCommonRing = null;\r\n\r\n for (let i = 0; i < commonRings.length; i++) {\r\n let ring = this.getRing(commonRings[i]);\r\n let size = ring.getSize();\r\n\r\n if (ring.isBenzeneLike(this.graph.vertices)) {\r\n return ring;\r\n } else if (size > maxSize) {\r\n maxSize = size;\r\n largestCommonRing = ring;\r\n }\r\n }\r\n\r\n return largestCommonRing;\r\n }\r\n\r\n /**\r\n * Returns an array of vertices positioned at a specified location.\r\n *\r\n * @param {Vector2} position The position to search for vertices.\r\n * @param {Number} radius The radius within to search.\r\n * @param {Number} excludeVertexId A vertex id to be excluded from the search results.\r\n * @returns {Number[]} An array containing vertex ids in a given location.\r\n */\r\n getVerticesAt(position, radius, excludeVertexId) {\r\n let locals = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.id === excludeVertexId || !vertex.positioned) {\r\n continue;\r\n }\r\n\r\n let distance = position.distanceSq(vertex.position);\r\n\r\n if (distance <= radius * radius) {\r\n locals.push(vertex.id);\r\n }\r\n }\r\n\r\n return locals;\r\n }\r\n\r\n /**\r\n * Returns the closest vertex (connected as well as unconnected).\r\n *\r\n * @param {Vertex} vertex The vertex of which to find the closest other vertex.\r\n * @returns {Vertex} The closest vertex.\r\n */\r\n getClosestVertex(vertex) {\r\n let minDist = 99999;\r\n let minVertex = null;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i];\r\n\r\n if (v.id === vertex.id) {\r\n continue;\r\n }\r\n\r\n let distSq = vertex.position.distanceSq(v.position);\r\n\r\n if (distSq < minDist) {\r\n minDist = distSq;\r\n minVertex = v;\r\n }\r\n }\r\n\r\n return minVertex;\r\n }\r\n\r\n /**\r\n * Add a ring to this representation of a molecule.\r\n *\r\n * @param {Ring} ring A new ring.\r\n * @returns {Number} The ring id of the new ring.\r\n */\r\n addRing(ring) {\r\n ring.id = this.ringIdCounter++;\r\n this.rings.push(ring);\r\n\r\n return ring.id;\r\n }\r\n\r\n /**\r\n * Removes a ring from the array of rings associated with the current molecule.\r\n *\r\n * @param {Number} ringId A ring id.\r\n */\r\n removeRing(ringId) {\r\n this.rings = this.rings.filter(function (item) {\r\n return item.id !== ringId;\r\n });\r\n\r\n // Also remove ring connections involving this ring\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.firstRingId !== ringId && item.secondRingId !== ringId;\r\n });\r\n\r\n // Remove the ring as neighbour of other rings\r\n for (var i = 0; i < this.rings.length; i++) {\r\n let r = this.rings[i];\r\n r.neighbours = r.neighbours.filter(function (item) {\r\n return item !== ringId;\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets a ring object from the array of rings associated with the current molecule by its id. The ring id is not equal to the index, since rings can be added and removed when processing bridged rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @returns {Ring} A ring associated with the current molecule.\r\n */\r\n getRing(ringId) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].id == ringId) {\r\n return this.rings[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Add a ring connection to this representation of a molecule.\r\n *\r\n * @param {RingConnection} ringConnection A new ringConnection.\r\n * @returns {Number} The ring connection id of the new ring connection.\r\n */\r\n addRingConnection(ringConnection) {\r\n ringConnection.id = this.ringConnectionIdCounter++;\r\n this.ringConnections.push(ringConnection);\r\n\r\n return ringConnection.id;\r\n }\r\n\r\n /**\r\n * Removes a ring connection from the array of rings connections associated with the current molecule.\r\n *\r\n * @param {Number} ringConnectionId A ring connection id.\r\n */\r\n removeRingConnection(ringConnectionId) {\r\n this.ringConnections = this.ringConnections.filter(function (item) {\r\n return item.id !== ringConnectionId;\r\n });\r\n }\r\n\r\n /**\r\n * Removes all ring connections between two vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n */\r\n removeRingConnectionsBetween(vertexIdA, vertexIdB) {\r\n let toRemove = Array();\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let ringConnection = this.ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === vertexIdA && ringConnection.secondRingId === vertexIdB ||\r\n ringConnection.firstRingId === vertexIdB && ringConnection.secondRingId === vertexIdA) {\r\n toRemove.push(ringConnection.id);\r\n }\r\n }\r\n\r\n for (let i = 0; i < toRemove.length; i++) {\r\n this.removeRingConnection(toRemove[i]);\r\n }\r\n }\r\n\r\n /**\r\n * Get a ring connection with a given id.\r\n *\r\n * @param {Number} id\r\n * @returns {RingConnection} The ring connection with the specified id.\r\n */\r\n getRingConnection(id) {\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n if (this.ringConnections[i].id == id) {\r\n return this.ringConnections[i];\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the ring connections between a ring and a set of rings.\r\n *\r\n * @param {Number} ringId A ring id.\r\n * @param {Number[]} ringIds An array of ring ids.\r\n * @returns {Number[]} An array of ring connection ids.\r\n */\r\n getRingConnections(ringId, ringIds) {\r\n let ringConnections = Array();\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n let rc = this.ringConnections[i];\r\n\r\n for (let j = 0; j < ringIds.length; j++) {\r\n let id = ringIds[j];\r\n\r\n if (rc.firstRingId === ringId && rc.secondRingId === id ||\r\n rc.firstRingId === id && rc.secondRingId === ringId) {\r\n ringConnections.push(rc.id);\r\n }\r\n }\r\n }\r\n\r\n return ringConnections;\r\n }\r\n\r\n /**\r\n * Returns the overlap score of the current molecule based on its positioned vertices. The higher the score, the more overlaps occur in the structure drawing.\r\n *\r\n * @returns {Object} Returns the total overlap score and the overlap score of each vertex sorted by score (higher to lower). Example: { total: 99, scores: [ { id: 0, score: 22 }, ... ] }\r\n */\r\n getOverlapScore() {\r\n let total = 0.0;\r\n let overlapScores = new Float32Array(this.graph.vertices.length);\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n overlapScores[i] = 0;\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let j = this.graph.vertices.length;\r\n while (--j > i) {\r\n let a = this.graph.vertices[i];\r\n let b = this.graph.vertices[j];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let dist = Vector2.subtract(a.position, b.position).lengthSq();\r\n\r\n if (dist < this.opts.bondLengthSq) {\r\n let weighted = (this.opts.bondLength - Math.sqrt(dist)) / this.opts.bondLength;\r\n total += weighted;\r\n overlapScores[i] += weighted;\r\n overlapScores[j] += weighted;\r\n }\r\n }\r\n }\r\n\r\n let sortable = Array();\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n sortable.push({\r\n id: i,\r\n score: overlapScores[i]\r\n });\r\n }\r\n\r\n sortable.sort(function (a, b) {\r\n return b.score - a.score;\r\n });\r\n\r\n return {\r\n total: total,\r\n scores: sortable,\r\n vertexScores: overlapScores\r\n };\r\n }\r\n\r\n /**\r\n * When drawing a double bond, choose the side to place the double bond. E.g. a double bond should always been drawn inside a ring.\r\n *\r\n * @param {Vertex} vertexA A vertex.\r\n * @param {Vertex} vertexB A vertex.\r\n * @param {Vector2[]} sides An array containing the two normals of the line spanned by the two provided vertices.\r\n * @returns {Object} Returns an object containing the following information: {\r\n totalSideCount: Counts the sides of each vertex in the molecule, is an array [ a, b ],\r\n totalPosition: Same as position, but based on entire molecule,\r\n sideCount: Counts the sides of each neighbour, is an array [ a, b ],\r\n position: which side to position the second bond, is 0 or 1, represents the index in the normal array. This is based on only the neighbours\r\n anCount: the number of neighbours of vertexA,\r\n bnCount: the number of neighbours of vertexB\r\n }\r\n */\r\n chooseSide(vertexA, vertexB, sides) {\r\n // Check which side has more vertices\r\n // Get all the vertices connected to the both ends\r\n let an = vertexA.getNeighbours(vertexB.id);\r\n let bn = vertexB.getNeighbours(vertexA.id);\r\n let anCount = an.length;\r\n let bnCount = bn.length;\r\n\r\n // All vertices connected to the edge vertexA to vertexB\r\n let tn = ArrayHelper.merge(an, bn);\r\n\r\n // Only considering the connected vertices\r\n let sideCount = [0, 0];\r\n\r\n for (let i = 0; i < tn.length; i++) {\r\n let v = this.graph.vertices[tn[i]].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n sideCount[0]++;\r\n } else {\r\n sideCount[1]++;\r\n }\r\n }\r\n\r\n // Considering all vertices in the graph, this is to resolve ties\r\n // from the above side counts\r\n let totalSideCount = [0, 0];\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let v = this.graph.vertices[i].position;\r\n\r\n if (v.sameSideAs(vertexA.position, vertexB.position, sides[0])) {\r\n totalSideCount[0]++;\r\n } else {\r\n totalSideCount[1]++;\r\n }\r\n }\r\n\r\n return {\r\n totalSideCount: totalSideCount,\r\n totalPosition: totalSideCount[0] > totalSideCount[1] ? 0 : 1,\r\n sideCount: sideCount,\r\n position: sideCount[0] > sideCount[1] ? 0 : 1,\r\n anCount: anCount,\r\n bnCount: bnCount\r\n };\r\n }\r\n\r\n /**\r\n * Sets the center for a ring.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n setRingCenter(ring) {\r\n let ringSize = ring.getSize();\r\n let total = new Vector2(0, 0);\r\n\r\n for (let i = 0; i < ringSize; i++) {\r\n total.add(this.graph.vertices[ring.members[i]].position);\r\n }\r\n\r\n ring.center = total.divide(ringSize);\r\n }\r\n\r\n /**\r\n * Gets the center of a ring contained within a bridged ring and containing a given vertex.\r\n *\r\n * @param {Ring} ring A bridged ring.\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {Vector2} The center of the subring that containing the vertex.\r\n */\r\n getSubringCenter(ring, vertex) {\r\n let rings = vertex.value.originalRings;\r\n let center = ring.center;\r\n let smallest = Number.MAX_VALUE;\r\n\r\n // Always get the smallest ring.\r\n for (let i = 0; i < rings.length; i++) {\r\n for (let j = 0; j < ring.rings.length; j++) {\r\n if (rings[i] === ring.rings[j].id) {\r\n if (ring.rings[j].getSize() < smallest) {\r\n center = ring.rings[j].center;\r\n smallest = ring.rings[j].getSize();\r\n }\r\n }\r\n }\r\n }\r\n\r\n return center;\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let that = this;\r\n let drawn = Array(this.graph.edges.length);\r\n drawn.fill(false);\r\n\r\n this.graph.traverseBF(0, function (vertex) {\r\n let edges = that.graph.getEdges(vertex.id);\r\n for (let i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n that.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (this.isRingAromatic(ring)) {\r\n this.canvasWrapper.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bonds to the canvas.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let that = this;\r\n let edge = this.graph.edges[edgeId];\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n let elementA = vertexA.value.element;\r\n let elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && this.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position;\r\n let b = vertexB.position;\r\n let normals = this.getEdgeNormals(edge);\r\n\r\n // Create a point on each side of the line\r\n let sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || this.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && this.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = this.areVerticesInSameRing(vertexA, vertexB);\r\n let s = this.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = this.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n }\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n this.canvasWrapper.drawLine(line, true);\r\n } else {\r\n this.canvasWrapper.drawLine(line);\r\n }\r\n\r\n // The normal edge\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.center || vertexA.isTerminal() && vertexB.isTerminal()) {\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1) {\r\n // Both lines are the same length here\r\n // Add the spacing to the edges (which are of unit length)\r\n normals[0].multiplyScalar(that.opts.halfBondSpacing);\r\n normals[1].multiplyScalar(that.opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n } else if (s.sideCount[0] > s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.sideCount[0] < s.sideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] > s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (s.totalSideCount[0] <= s.totalSideCount[1]) {\r\n normals[0].multiplyScalar(that.opts.bondSpacing);\r\n normals[1].multiplyScalar(that.opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n line.shorten(this.opts.bondLength - this.opts.shortBondLength * this.opts.bondLength);\r\n this.canvasWrapper.drawLine(line);\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(that.opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay));\r\n\r\n this.canvasWrapper.drawLine(lineA);\r\n this.canvasWrapper.drawLine(lineB);\r\n\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, false, false, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n this.canvasWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else if (edge.wedge === 'down') {\r\n this.canvasWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n } else {\r\n this.canvasWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB, this.isDrawDecayPoint(edge.isDecay)));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n this.canvasWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(this.graph.vertices);\r\n let isTerminal = this.opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (this.opts.atomVisualization === 'allballs') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || this.graph.vertices.length === 1) {\r\n if (this.opts.atomVisualization === 'default') {\r\n this.canvasWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (this.opts.atomVisualization === 'balls') {\r\n this.canvasWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = this.graph.vertices[vertex.neighbours[0]].position;\r\n let b = this.graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n this.canvasWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n // this.canvasWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (this.opts.debug) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let center = this.rings[i].center;\r\n this.canvasWrapper.drawDebugPoint(center.x, center.y, 'r: ' + this.rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Position the vertices according to their bonds and properties.\r\n */\r\n position() {\r\n let startVertex = null;\r\n\r\n // Always start drawing at a bridged ring if there is one\r\n // If not, start with a ring\r\n // else, start with 0\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n if (this.graph.vertices[i].value.bridgedRing !== null) {\r\n startVertex = this.graph.vertices[i];\r\n break;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n if (this.rings[i].isBridged) {\r\n startVertex = this.graph.vertices[this.rings[i].members[0]];\r\n }\r\n }\r\n\r\n if (this.rings.length > 0 && startVertex === null) {\r\n startVertex = this.graph.vertices[this.rings[0].members[0]];\r\n }\r\n\r\n if (startVertex === null) {\r\n startVertex = this.graph.vertices[0];\r\n }\r\n\r\n this.createNextBond(startVertex, null, 0.0);\r\n }\r\n\r\n /**\r\n * Stores the current information associated with rings.\r\n */\r\n backupRingInformation() {\r\n this.originalRings = Array();\r\n this.originalRingConnections = Array();\r\n\r\n for (let i = 0; i < this.rings.length; i++) {\r\n this.originalRings.push(this.rings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.ringConnections.length; i++) {\r\n this.originalRingConnections.push(this.ringConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.backupRings();\r\n }\r\n }\r\n\r\n /**\r\n * Restores the most recently backed up information associated with rings.\r\n */\r\n restoreRingInformation() {\r\n // Get the subring centers from the bridged rings\r\n let bridgedRings = this.getBridgedRings();\r\n\r\n this.rings = Array();\r\n this.ringConnections = Array();\r\n\r\n for (let i = 0; i < bridgedRings.length; i++) {\r\n let bridgedRing = bridgedRings[i];\r\n\r\n for (var j = 0; j < bridgedRing.rings.length; j++) {\r\n let ring = bridgedRing.rings[j];\r\n this.originalRings[ring.id].center = ring.center;\r\n }\r\n }\r\n\r\n for (let i = 0; i < this.originalRings.length; i++) {\r\n this.rings.push(this.originalRings[i]);\r\n }\r\n\r\n for (let i = 0; i < this.originalRingConnections.length; i++) {\r\n this.ringConnections.push(this.originalRingConnections[i]);\r\n }\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n this.graph.vertices[i].value.restoreRings();\r\n }\r\n }\r\n\r\n // TODO: This needs some cleaning up\r\n\r\n /**\r\n * Creates a new ring, that is, positiones all the vertices inside a ring.\r\n *\r\n * @param {Ring} ring The ring to position.\r\n * @param {(Vector2|null)} [center=null] The center of the ring to be created.\r\n * @param {(Vertex|null)} [startVertex=null] The first vertex to be positioned inside the ring.\r\n * @param {(Vertex|null)} [previousVertex=null] The last vertex that was positioned.\r\n * @param {Boolean} [previousVertex=false] A boolean indicating whether or not this ring was force positioned already - this is needed after force layouting a ring, in order to draw rings connected to it.\r\n */\r\n createRing(ring, center = null, startVertex = null, previousVertex = null) {\r\n if (ring.positioned) {\r\n return;\r\n }\r\n\r\n center = center ? center : new Vector2(0, 0);\r\n\r\n let orderedNeighbours = ring.getOrderedNeighbours(this.ringConnections);\r\n let startingAngle = startVertex ? Vector2.subtract(startVertex.position, center).angle() : 0;\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let angle = MathHelper.centralAngle(ring.getSize());\r\n\r\n ring.centralAngle = angle;\r\n\r\n let a = startingAngle;\r\n let that = this;\r\n let startVertexId = (startVertex) ? startVertex.id : null;\r\n\r\n if (ring.members.indexOf(startVertexId) === -1) {\r\n if (startVertex) {\r\n startVertex.positioned = false;\r\n }\r\n\r\n startVertexId = ring.members[0];\r\n }\r\n\r\n // If the ring is bridged, then draw the vertices inside the ring\r\n // using a force based approach\r\n if (ring.isBridged) {\r\n this.graph.kkLayout(ring.members.slice(), center, startVertex.id, ring, this.opts.bondLength,\r\n this.opts.kkThreshold, this.opts.kkInnerThreshold, this.opts.kkMaxIteration,\r\n this.opts.kkMaxInnerIteration, this.opts.kkMaxEnergy);\r\n ring.positioned = true;\r\n\r\n // Update the center of the bridged ring\r\n this.setRingCenter(ring);\r\n center = ring.center;\r\n\r\n // Setting the centers for the subrings\r\n for (let i = 0; i < ring.rings.length; i++) {\r\n this.setRingCenter(ring.rings[i]);\r\n }\r\n } else {\r\n ring.eachMember(this.graph.vertices, function (v) {\r\n let vertex = that.graph.vertices[v];\r\n\r\n if (!vertex.positioned) {\r\n vertex.setPosition(center.x + Math.cos(a) * radius, center.y + Math.sin(a) * radius);\r\n }\r\n\r\n a += angle;\r\n\r\n if (!ring.isBridged || ring.rings.length < 3) {\r\n vertex.angle = a;\r\n vertex.positioned = true;\r\n }\r\n }, startVertexId, (previousVertex) ? previousVertex.id : null);\r\n }\r\n\r\n ring.positioned = true;\r\n ring.center = center;\r\n\r\n // Draw neighbours in decreasing order of connectivity\r\n for (let i = 0; i < orderedNeighbours.length; i++) {\r\n let neighbour = this.getRing(orderedNeighbours[i].neighbour);\r\n\r\n if (neighbour.positioned) {\r\n continue;\r\n }\r\n\r\n let vertices = RingConnection.getVertices(this.ringConnections, ring.id, neighbour.id);\r\n\r\n if (vertices.length === 2) {\r\n // This ring is a fused ring\r\n ring.isFused = true;\r\n neighbour.isFused = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n let vertexB = this.graph.vertices[vertices[1]];\r\n\r\n // Get middle between vertex A and B\r\n let midpoint = Vector2.midpoint(vertexA.position, vertexB.position);\r\n\r\n // Get the normals to the line between A and B\r\n let normals = Vector2.normals(vertexA.position, vertexB.position);\r\n\r\n // Normalize the normals\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n // Set length from middle of side to center (the apothem)\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n let apothem = MathHelper.apothem(r, neighbour.getSize());\r\n\r\n normals[0].multiplyScalar(apothem).add(midpoint);\r\n normals[1].multiplyScalar(apothem).add(midpoint);\r\n\r\n // Pick the normal which results in a larger distance to the previous center\r\n // Also check whether it's inside another ring\r\n let nextCenter = normals[0];\r\n if (Vector2.subtract(center, normals[1]).lengthSq() > Vector2.subtract(center, normals[0]).lengthSq()) {\r\n nextCenter = normals[1];\r\n }\r\n\r\n // Get the vertex (A or B) which is in clock-wise direction of the other\r\n let posA = Vector2.subtract(vertexA.position, nextCenter);\r\n let posB = Vector2.subtract(vertexB.position, nextCenter);\r\n\r\n if (posA.clockwise(posB) === -1) {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA, vertexB);\r\n }\r\n } else {\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexB, vertexA);\r\n }\r\n }\r\n } else if (vertices.length === 1) {\r\n // This ring is a spiro\r\n ring.isSpiro = true;\r\n neighbour.isSpiro = true;\r\n\r\n let vertexA = this.graph.vertices[vertices[0]];\r\n\r\n // Get the vector pointing from the shared vertex to the new centpositioner\r\n let nextCenter = Vector2.subtract(center, vertexA.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n // Get the distance from the vertex to the center\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, neighbour.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertexA.position);\r\n\r\n if (!neighbour.positioned) {\r\n this.createRing(neighbour, nextCenter, vertexA);\r\n }\r\n }\r\n }\r\n\r\n // Next, draw atoms that are not part of a ring that are directly attached to this ring\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let ringMember = this.graph.vertices[ring.members[i]];\r\n let ringMemberNeighbours = ringMember.neighbours;\r\n\r\n // If there are multiple, the ovlerap will be resolved in the appropriate step\r\n for (let j = 0; j < ringMemberNeighbours.length; j++) {\r\n let v = this.graph.vertices[ringMemberNeighbours[j]];\r\n\r\n if (v.positioned) {\r\n continue;\r\n }\r\n\r\n v.value.isConnectedToRing = true;\r\n this.createNextBond(v, ringMember, 0.0);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Rotate an entire subtree by an angle around a center.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree that is to rotate.\r\n * @param {Number} angle An angle in randians.\r\n * @param {Vector2} center The rotational center.\r\n */\r\n rotateSubtree(vertexId, parentVertexId, angle, center) {\r\n let that = this;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n vertex.position.rotateAround(angle, center);\r\n\r\n for (var i = 0; i < vertex.value.anchoredRings.length; i++) {\r\n let ring = that.rings[vertex.value.anchoredRings[i]];\r\n\r\n if (ring) {\r\n ring.center.rotateAround(angle, center);\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Gets the overlap score of a subtree.\r\n *\r\n * @param {Number} vertexId A vertex id (the root of the sub-tree).\r\n * @param {Number} parentVertexId A vertex id in the previous direction of the subtree.\r\n * @param {Number[]} vertexOverlapScores An array containing the vertex overlap scores indexed by vertex id.\r\n * @returns {Object} An object containing the total overlap score and the center of mass of the subtree weighted by overlap score { value: 0.2, center: new Vector2() }.\r\n */\r\n getSubtreeOverlapScore(vertexId, parentVertexId, vertexOverlapScores) {\r\n let that = this;\r\n let score = 0;\r\n let center = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n this.graph.traverseTree(vertexId, parentVertexId, function (vertex) {\r\n if (!vertex.value.isDrawn) {\r\n return;\r\n }\r\n\r\n let s = vertexOverlapScores[vertex.id];\r\n if (s > that.opts.overlapSensitivity) {\r\n score += s;\r\n count++;\r\n }\r\n\r\n let position = that.graph.vertices[vertex.id].position.clone();\r\n position.multiplyScalar(s);\r\n center.add(position);\r\n });\r\n\r\n center.divide(score);\r\n\r\n return {\r\n value: score / count,\r\n center: center\r\n };\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass.\r\n *\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMass() {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Returns the current (positioned vertices so far) center of mass in the neighbourhood of a given position.\r\n *\r\n * @param {Vector2} vec The point at which to look for neighbours.\r\n * @param {Number} [r=currentBondLength*2.0] The radius of vertices to include.\r\n * @returns {Vector2} The current center of mass.\r\n */\r\n getCurrentCenterOfMassInNeigbourhood(vec, r = this.opts.bondLength * 2.0) {\r\n let total = new Vector2(0, 0);\r\n let count = 0;\r\n let rSq = r * r;\r\n\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (vertex.positioned && vec.distanceSq(vertex.position) < rSq) {\r\n total.add(vertex.position);\r\n count++;\r\n }\r\n }\r\n\r\n return total.divide(count);\r\n }\r\n\r\n /**\r\n * Resolve primary (exact) overlaps, such as two vertices that are connected to the same ring vertex.\r\n */\r\n resolvePrimaryOverlaps() {\r\n let overlaps = Array();\r\n let done = Array(this.graph.vertices.length);\r\n\r\n // Looking for overlaps created by two bonds coming out of a ring atom, which both point straight\r\n // away from the ring and are thus perfectly overlapping.\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n for (let j = 0; j < ring.members.length; j++) {\r\n let vertex = this.graph.vertices[ring.members[j]];\r\n\r\n if (done[vertex.id]) {\r\n continue;\r\n }\r\n\r\n done[vertex.id] = true;\r\n\r\n let nonRingNeighbours = this.getNonRingNeighbours(vertex.id);\r\n\r\n if (nonRingNeighbours.length > 1) {\r\n // Look for rings where there are atoms with two bonds outside the ring (overlaps)\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n } else if (nonRingNeighbours.length === 1 && vertex.value.rings.length === 2) {\r\n // Look for bonds coming out of joined rings to adjust the angle, an example is: C1=CC(=CC=C1)[C@]12SCCN1CC1=CC=CC=C21\r\n // where the angle has to be adjusted to account for fused ring\r\n let rings = Array();\r\n\r\n for (let k = 0; k < vertex.value.rings.length; k++) {\r\n rings.push(vertex.value.rings[k]);\r\n }\r\n\r\n overlaps.push({\r\n common: vertex,\r\n rings: rings,\r\n vertices: nonRingNeighbours\r\n });\r\n }\r\n }\r\n }\r\n\r\n for (let i = 0; i < overlaps.length; i++) {\r\n let overlap = overlaps[i];\r\n\r\n if (overlap.vertices.length === 2) {\r\n let a = overlap.vertices[0];\r\n let b = overlap.vertices[1];\r\n\r\n if (!a.value.isDrawn || !b.value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let angle = (2 * Math.PI - this.getRing(overlap.rings[0]).getAngle()) / 6.0;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -angle, overlap.common.position);\r\n\r\n // Decide which way to rotate the vertices depending on the effect it has on the overlap score\r\n let overlapScore = this.getOverlapScore();\r\n let subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n let subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n let total = subTreeOverlapA.value + subTreeOverlapB.value;\r\n\r\n this.rotateSubtree(a.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n\r\n overlapScore = this.getOverlapScore();\r\n subTreeOverlapA = this.getSubtreeOverlapScore(a.id, overlap.common.id, overlapScore.vertexScores);\r\n subTreeOverlapB = this.getSubtreeOverlapScore(b.id, overlap.common.id, overlapScore.vertexScores);\r\n\r\n if (subTreeOverlapA.value + subTreeOverlapB.value > total) {\r\n this.rotateSubtree(a.id, overlap.common.id, 2.0 * angle, overlap.common.position);\r\n this.rotateSubtree(b.id, overlap.common.id, -2.0 * angle, overlap.common.position);\r\n }\r\n } else if (overlap.vertices.length === 1) {\r\n if (overlap.rings.length === 2) {\r\n // TODO: Implement for more overlap resolution\r\n // console.log(overlap);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Resolve secondary overlaps. Those overlaps are due to the structure turning back on itself.\r\n *\r\n * @param {Object[]} scores An array of objects sorted descending by score.\r\n * @param {Number} scores[].id A vertex id.\r\n * @param {Number} scores[].score The overlap score associated with the vertex id.\r\n */\r\n resolveSecondaryOverlaps(scores) {\r\n for (let i = 0; i < scores.length; i++) {\r\n if (scores[i].score > this.opts.overlapSensitivity) {\r\n let vertex = this.graph.vertices[scores[i].id];\r\n\r\n if (vertex.isTerminal()) {\r\n let closest = this.getClosestVertex(vertex);\r\n\r\n if (closest) {\r\n // If one of the vertices is the first one, the previous vertex is not the central vertex but the dummy\r\n // so take the next rather than the previous, which is vertex 1\r\n let closestPosition = null;\r\n\r\n if (closest.isTerminal()) {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.previousPosition\r\n } else {\r\n closestPosition = closest.id === 0 ? this.graph.vertices[1].position : closest.position\r\n }\r\n\r\n let vertexPreviousPosition = vertex.id === 0 ? this.graph.vertices[1].position : vertex.previousPosition;\r\n\r\n vertex.position.rotateAwayFrom(closestPosition, vertexPreviousPosition, MathHelper.toRad(20));\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the last non-null or 0 angle vertex.\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex} The last vertex with an angle that was not 0 or null.\r\n */\r\n getLastVertexWithAngle(vertexId) {\r\n let angle = 0;\r\n let vertex = null;\r\n\r\n while (!angle && vertexId) {\r\n vertex = this.graph.vertices[vertexId];\r\n angle = vertex.angle;\r\n vertexId = vertex.parentVertexId;\r\n }\r\n\r\n return vertex;\r\n }\r\n\r\n /**\r\n * Positiones the next vertex thus creating a bond.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @param {Vertex} [previousVertex=null] The previous vertex which has been positioned.\r\n * @param {Number} [angle=0.0] The (global) angle of the vertex.\r\n * @param {Boolean} [originShortest=false] Whether the origin is the shortest subtree in the branch.\r\n * @param {Boolean} [skipPositioning=false] Whether or not to skip positioning and just check the neighbours.\r\n */\r\n createNextBond(vertex, previousVertex = null, angle = 0.0, originShortest = false, skipPositioning = false) {\r\n if (vertex.positioned && !skipPositioning) {\r\n return;\r\n }\r\n\r\n // If the double bond config was set on this vertex, do not check later\r\n let doubleBondConfigSet = false;\r\n\r\n // Keeping track of configurations around double bonds\r\n if (previousVertex) {\r\n let edge = this.graph.getEdge(vertex.id, previousVertex.id);\r\n\r\n if ((edge.bondType === '/' || edge.bondType === '\\\\') && ++this.doubleBondConfigCount % 2 === 1) {\r\n if (this.doubleBondConfig === null) {\r\n this.doubleBondConfig = edge.bondType;\r\n doubleBondConfigSet = true;\r\n\r\n // Switch if the bond is a branch bond and previous vertex is the first\r\n // TODO: Why is it different with the first vertex?\r\n if (previousVertex.parentVertexId === null && vertex.value.branchBond) {\r\n if (this.doubleBondConfig === '/') {\r\n this.doubleBondConfig = '\\\\';\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n this.doubleBondConfig = '/';\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If the current node is the member of one ring, then point straight away\r\n // from the center of the ring. However, if the current node is a member of\r\n // two rings, point away from the middle of the centers of the two rings\r\n if (!skipPositioning) {\r\n if (!previousVertex) {\r\n // Add a (dummy) previous position if there is no previous vertex defined\r\n // Since the first vertex is at (0, 0), create a vector at (bondLength, 0)\r\n // and rotate it by 90°\r\n\r\n let dummy = new Vector2(this.opts.bondLength, 0);\r\n dummy.rotate(MathHelper.toRad(-60));\r\n\r\n vertex.previousPosition = dummy;\r\n vertex.setPosition(this.opts.bondLength, 0);\r\n vertex.angle = MathHelper.toRad(-60);\r\n\r\n // Do not position the vertex if it belongs to a bridged ring that is positioned using a layout algorithm.\r\n if (vertex.value.bridgedRing === null) {\r\n vertex.positioned = true;\r\n }\r\n } else if (previousVertex.value.rings.length > 0) {\r\n let neighbours = previousVertex.neighbours;\r\n let joinedVertex = null;\r\n let pos = new Vector2(0.0, 0.0);\r\n\r\n if (previousVertex.value.bridgedRing === null && previousVertex.value.rings.length > 1) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n if (ArrayHelper.containsAll(neighbour.value.rings, previousVertex.value.rings)) {\r\n joinedVertex = neighbour;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (joinedVertex === null) {\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let v = this.graph.vertices[neighbours[i]];\r\n\r\n if (v.positioned && this.areVerticesInSameRing(v, previousVertex)) {\r\n pos.add(Vector2.subtract(v.position, previousVertex.position));\r\n }\r\n }\r\n\r\n pos.invert().normalize().multiplyScalar(this.opts.bondLength).add(previousVertex.position);\r\n } else {\r\n pos = joinedVertex.position.clone().rotateAround(Math.PI, previousVertex.position);\r\n }\r\n\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.setPositionFromVector(pos);\r\n vertex.positioned = true;\r\n } else {\r\n // If the previous vertex was not part of a ring, draw a bond based\r\n // on the global angle of the previous bond\r\n let v = new Vector2(this.opts.bondLength, 0);\r\n\r\n v.rotate(angle);\r\n v.add(previousVertex.position);\r\n\r\n vertex.setPositionFromVector(v);\r\n vertex.previousPosition = previousVertex.position;\r\n vertex.positioned = true;\r\n }\r\n }\r\n\r\n // Go to next vertex\r\n // If two rings are connected by a bond ...\r\n if (vertex.value.bridgedRing !== null) {\r\n let nextRing = this.getRing(vertex.value.bridgedRing);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.members.length);\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else if (vertex.value.rings.length > 0) {\r\n let nextRing = this.getRing(vertex.value.rings[0]);\r\n\r\n if (!nextRing.positioned) {\r\n let nextCenter = Vector2.subtract(vertex.previousPosition, vertex.position);\r\n\r\n nextCenter.invert();\r\n nextCenter.normalize();\r\n\r\n let r = MathHelper.polyCircumradius(this.opts.bondLength, nextRing.getSize());\r\n\r\n nextCenter.multiplyScalar(r);\r\n nextCenter.add(vertex.position);\r\n\r\n this.createRing(nextRing, nextCenter, vertex);\r\n }\r\n } else {\r\n // Draw the non-ring vertices connected to this one\r\n let isStereoCenter = vertex.value.isStereoCenter;\r\n let tmpNeighbours = vertex.getNeighbours();\r\n let neighbours = Array();\r\n\r\n // Remove neighbours that are not drawn\r\n for (let i = 0; i < tmpNeighbours.length; i++) {\r\n if (this.graph.vertices[tmpNeighbours[i]].value.isDrawn) {\r\n neighbours.push(tmpNeighbours[i]);\r\n }\r\n }\r\n\r\n // Remove the previous vertex (which has already been drawn)\r\n if (previousVertex) {\r\n neighbours = ArrayHelper.remove(neighbours, previousVertex.id);\r\n }\r\n\r\n let previousAngle = vertex.getAngle();\r\n\r\n if (neighbours.length === 1) {\r\n let nextVertex = this.graph.vertices[neighbours[0]];\r\n\r\n // Make a single chain always cis except when there's a tribble (yes, this is a Star Trek reference) bond\r\n // or if there are successive double bonds. Added a ring check because if there is an aromatic ring the ring bond inside the ring counts as a double bond and leads to =-= being straight.\r\n if ((vertex.value.bondType === '#' || (previousVertex && previousVertex.value.bondType === '#')) ||\r\n vertex.value.bondType === '=' && previousVertex && previousVertex.value.rings.length === 0 &&\r\n previousVertex.value.bondType === '=' && vertex.value.branchBond !== '-') {\r\n vertex.value.drawExplicit = false;\r\n\r\n if (previousVertex) {\r\n let straightEdge1 = this.graph.getEdge(vertex.id, previousVertex.id);\r\n straightEdge1.center = true;\r\n }\r\n\r\n let straightEdge2 = this.graph.getEdge(vertex.id, nextVertex.id);\r\n straightEdge2.center = true;\r\n\r\n if (vertex.value.bondType === '#' || previousVertex && previousVertex.value.bondType === '#') {\r\n nextVertex.angle = 0.0;\r\n }\r\n\r\n nextVertex.drawExplicit = true;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else if (previousVertex && previousVertex.value.rings.length > 0) {\r\n // If coming out of a ring, always draw away from the center of mass\r\n let proposedAngleA = MathHelper.toRad(60);\r\n let proposedAngleB = -proposedAngleA;\r\n\r\n let proposedVectorA = new Vector2(this.opts.bondLength, 0);\r\n let proposedVectorB = new Vector2(this.opts.bondLength, 0);\r\n\r\n proposedVectorA.rotate(proposedAngleA).add(vertex.position);\r\n proposedVectorB.rotate(proposedAngleB).add(vertex.position);\r\n\r\n // let centerOfMass = this.getCurrentCenterOfMassInNeigbourhood(vertex.position, 100);\r\n let centerOfMass = this.getCurrentCenterOfMass();\r\n let distanceA = proposedVectorA.distanceSq(centerOfMass);\r\n let distanceB = proposedVectorB.distanceSq(centerOfMass);\r\n\r\n nextVertex.angle = distanceA < distanceB ? proposedAngleB : proposedAngleA;\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n } else {\r\n let a = vertex.angle;\r\n // Take the min and max if the previous angle was in a 4-neighbourhood (90° angles)\r\n // TODO: If a is null or zero, it should be checked whether or not this one should go cis or trans, that is,\r\n // it should go into the oposite direction of the last non-null or 0 previous vertex / angle.\r\n if (previousVertex && previousVertex.neighbours.length > 3) {\r\n if (a > 0) {\r\n a = Math.min(1.0472, a);\r\n } else if (a < 0) {\r\n a = Math.max(-1.0472, a);\r\n } else {\r\n a = 1.0472;\r\n }\r\n } else if (!a) {\r\n let v = this.getLastVertexWithAngle(vertex.id);\r\n a = v.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n }\r\n\r\n // Handle configuration around double bonds\r\n if (previousVertex && !doubleBondConfigSet) {\r\n let bondType = this.graph.getEdge(vertex.id, nextVertex.id).bondType;\r\n\r\n if (bondType === '/') {\r\n if (this.doubleBondConfig === '/') {\r\n // Nothing to do since it will be trans per default\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n a = -a;\r\n }\r\n this.doubleBondConfig = null;\r\n } else if (bondType === '\\\\') {\r\n if (this.doubleBondConfig === '/') {\r\n a = -a;\r\n } else if (this.doubleBondConfig === '\\\\') {\r\n // Nothing to do since it will be trans per default\r\n }\r\n this.doubleBondConfig = null;\r\n }\r\n }\r\n\r\n if (originShortest) {\r\n nextVertex.angle = a;\r\n } else {\r\n nextVertex.angle = -a;\r\n }\r\n\r\n this.createNextBond(nextVertex, vertex, previousAngle + nextVertex.angle);\r\n }\r\n } else if (neighbours.length === 2) {\r\n // If the previous vertex comes out of a ring, it doesn't have an angle set\r\n let a = vertex.angle;\r\n\r\n if (!a) {\r\n a = 1.0472;\r\n }\r\n\r\n // Check for the longer subtree - always go with cis for the longer subtree\r\n let subTreeDepthA = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let subTreeDepthB = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n\r\n let l = this.graph.vertices[neighbours[0]];\r\n let r = this.graph.vertices[neighbours[1]];\r\n\r\n l.value.subtreeDepth = subTreeDepthA;\r\n r.value.subtreeDepth = subTreeDepthB;\r\n\r\n // Also get the subtree for the previous direction (this is important when\r\n // the previous vertex is the shortest path)\r\n let subTreeDepthC = this.graph.getTreeDepth(previousVertex ? previousVertex.id : null, vertex.id);\r\n if (previousVertex) {\r\n previousVertex.value.subtreeDepth = subTreeDepthC;\r\n }\r\n\r\n let cis = 0;\r\n let trans = 1;\r\n\r\n // Carbons go always cis\r\n if (r.value.element === 'C' && l.value.element !== 'C' && subTreeDepthB > 1 && subTreeDepthA < 5) {\r\n cis = 1;\r\n trans = 0;\r\n } else if (r.value.element !== 'C' && l.value.element === 'C' && subTreeDepthA > 1 && subTreeDepthB < 5) {\r\n cis = 0;\r\n trans = 1;\r\n } else if (subTreeDepthB > subTreeDepthA) {\r\n cis = 1;\r\n trans = 0;\r\n }\r\n\r\n let cisVertex = this.graph.vertices[neighbours[cis]];\r\n let transVertex = this.graph.vertices[neighbours[trans]];\r\n\r\n // If the origin tree is the shortest, make them the main chain\r\n let originShortest = false;\r\n if (subTreeDepthC < subTreeDepthA && subTreeDepthC < subTreeDepthB) {\r\n originShortest = true;\r\n }\r\n\r\n transVertex.angle = a;\r\n cisVertex.angle = -a;\r\n\r\n if (this.doubleBondConfig === '\\\\') {\r\n if (transVertex.value.branchBond === '\\\\') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n } else if (this.doubleBondConfig === '/') {\r\n if (transVertex.value.branchBond === '/') {\r\n transVertex.angle = -a;\r\n cisVertex.angle = a;\r\n }\r\n }\r\n\r\n this.createNextBond(transVertex, vertex, previousAngle + transVertex.angle, originShortest);\r\n this.createNextBond(cisVertex, vertex, previousAngle + cisVertex.angle, originShortest);\r\n } else if (neighbours.length === 3) {\r\n // The vertex with the longest sub-tree should always go straight\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n\r\n let s = this.graph.vertices[neighbours[0]];\r\n let l = this.graph.vertices[neighbours[1]];\r\n let r = this.graph.vertices[neighbours[2]];\r\n\r\n s.value.subtreeDepth = d1;\r\n l.value.subtreeDepth = d2;\r\n r.value.subtreeDepth = d3;\r\n\r\n if (d2 > d1 && d2 > d3) {\r\n s = this.graph.vertices[neighbours[1]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[2]];\r\n } else if (d3 > d1 && d3 > d2) {\r\n s = this.graph.vertices[neighbours[2]];\r\n l = this.graph.vertices[neighbours[0]];\r\n r = this.graph.vertices[neighbours[1]];\r\n }\r\n\r\n // Create a cross if more than one subtree is of length > 1\r\n // or the vertex is connected to a ring\r\n if (previousVertex &&\r\n previousVertex.value.rings.length < 1 &&\r\n s.value.rings.length < 1 &&\r\n l.value.rings.length < 1 &&\r\n r.value.rings.length < 1 &&\r\n this.graph.getTreeDepth(l.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(r.id, vertex.id) === 1 &&\r\n this.graph.getTreeDepth(s.id, vertex.id) > 1) {\r\n\r\n s.angle = -vertex.angle;\r\n if (vertex.angle >= 0) {\r\n l.angle = MathHelper.toRad(30);\r\n r.angle = MathHelper.toRad(90);\r\n } else {\r\n l.angle = -MathHelper.toRad(30);\r\n r.angle = -MathHelper.toRad(90);\r\n }\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n } else {\r\n s.angle = 0.0;\r\n l.angle = MathHelper.toRad(90);\r\n r.angle = -MathHelper.toRad(90);\r\n\r\n this.createNextBond(s, vertex, previousAngle + s.angle);\r\n this.createNextBond(l, vertex, previousAngle + l.angle);\r\n this.createNextBond(r, vertex, previousAngle + r.angle);\r\n }\r\n } else if (neighbours.length === 4) {\r\n // The vertex with the longest sub-tree should always go to the reflected opposide direction\r\n let d1 = this.graph.getTreeDepth(neighbours[0], vertex.id);\r\n let d2 = this.graph.getTreeDepth(neighbours[1], vertex.id);\r\n let d3 = this.graph.getTreeDepth(neighbours[2], vertex.id);\r\n let d4 = this.graph.getTreeDepth(neighbours[3], vertex.id);\r\n\r\n let w = this.graph.vertices[neighbours[0]];\r\n let x = this.graph.vertices[neighbours[1]];\r\n let y = this.graph.vertices[neighbours[2]];\r\n let z = this.graph.vertices[neighbours[3]];\r\n\r\n w.value.subtreeDepth = d1;\r\n x.value.subtreeDepth = d2;\r\n y.value.subtreeDepth = d3;\r\n z.value.subtreeDepth = d4;\r\n\r\n if (d2 > d1 && d2 > d3 && d2 > d4) {\r\n w = this.graph.vertices[neighbours[1]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[2]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d3 > d1 && d3 > d2 && d3 > d4) {\r\n w = this.graph.vertices[neighbours[2]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[3]];\r\n } else if (d4 > d1 && d4 > d2 && d4 > d3) {\r\n w = this.graph.vertices[neighbours[3]];\r\n x = this.graph.vertices[neighbours[0]];\r\n y = this.graph.vertices[neighbours[1]];\r\n z = this.graph.vertices[neighbours[2]];\r\n }\r\n\r\n w.angle = -MathHelper.toRad(36);\r\n x.angle = MathHelper.toRad(36);\r\n y.angle = -MathHelper.toRad(108);\r\n z.angle = MathHelper.toRad(108);\r\n\r\n this.createNextBond(w, vertex, previousAngle + w.angle);\r\n this.createNextBond(x, vertex, previousAngle + x.angle);\r\n this.createNextBond(y, vertex, previousAngle + y.angle);\r\n this.createNextBond(z, vertex, previousAngle + z.angle);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Gets the vetex sharing the edge that is the common bond of two rings.\r\n *\r\n * @param {Vertex} vertex A vertex.\r\n * @returns {(Number|null)} The id of a vertex sharing the edge that is the common bond of two rings with the vertex provided or null, if none.\r\n */\r\n getCommonRingbondNeighbour(vertex) {\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n\r\n if (ArrayHelper.containsAll(neighbour.value.rings, vertex.value.rings)) {\r\n return neighbour;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /**\r\n * Check if a vector is inside any ring.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Boolean} A boolean indicating whether or not the point (vector) is inside any of the rings associated with the current molecule.\r\n */\r\n isPointInRing(vec) {\r\n for (let i = 0; i < this.rings.length; i++) {\r\n let ring = this.rings[i];\r\n\r\n if (!ring.positioned) {\r\n continue;\r\n }\r\n\r\n let radius = MathHelper.polyCircumradius(this.opts.bondLength, ring.getSize());\r\n let radiusSq = radius * radius;\r\n\r\n if (vec.distanceSq(ring.center) < radiusSq) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is part of a ring.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is part of a ring.\r\n */\r\n isEdgeInRing(edge) {\r\n let source = this.graph.vertices[edge.sourceId];\r\n let target = this.graph.vertices[edge.targetId];\r\n\r\n return this.areVerticesInSameRing(source, target);\r\n }\r\n\r\n /**\r\n * Check whether or not an edge is rotatable.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Boolean} A boolean indicating whether or not the edge is rotatable.\r\n */\r\n isEdgeRotatable(edge) {\r\n let vertexA = this.graph.vertices[edge.sourceId];\r\n let vertexB = this.graph.vertices[edge.targetId];\r\n\r\n // Only single bonds are rotatable\r\n if (edge.bondType !== '-') {\r\n return false;\r\n }\r\n\r\n // Do not rotate edges that have a further single bond to each side - do that!\r\n // If the bond is terminal, it doesn't make sense to rotate it\r\n // if (vertexA.getNeighbourCount() + vertexB.getNeighbourCount() < 5) {\r\n // return false;\r\n // }\r\n\r\n if (vertexA.isTerminal() || vertexB.isTerminal()) {\r\n return false;\r\n }\r\n\r\n // Ringbonds are not rotatable\r\n return !(vertexA.value.rings.length > 0 && vertexB.value.rings.length > 0 && this.areVerticesInSameRing(vertexA, vertexB));\r\n }\r\n\r\n /**\r\n * Check whether or not a ring is an implicitly defined aromatic ring (lower case smiles).\r\n *\r\n * @param {Ring} ring A ring.\r\n * @returns {Boolean} A boolean indicating whether or not a ring is implicitly defined as aromatic.\r\n */\r\n isRingAromatic(ring) {\r\n for (let i = 0; i < ring.members.length; i++) {\r\n let vertex = this.graph.vertices[ring.members[i]];\r\n\r\n if (!vertex.value.isPartOfAromaticRing) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Get the normals of an edge.\r\n *\r\n * @param {Edge} edge An edge.\r\n * @returns {Vector2[]} An array containing two vectors, representing the normals.\r\n */\r\n getEdgeNormals(edge) {\r\n let v1 = this.graph.vertices[edge.sourceId].position;\r\n let v2 = this.graph.vertices[edge.targetId].position;\r\n\r\n // Get the normalized normals for the edge\r\n return Vector2.units(v1, v2);\r\n }\r\n\r\n /**\r\n * Returns an array of vertices that are neighbouring a vertix but are not members of a ring (including bridges).\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Vertex[]} An array of vertices.\r\n */\r\n getNonRingNeighbours(vertexId) {\r\n let nrneighbours = Array();\r\n let vertex = this.graph.vertices[vertexId];\r\n let neighbours = vertex.neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n let neighbour = this.graph.vertices[neighbours[i]];\r\n let nIntersections = ArrayHelper.intersection(vertex.value.rings, neighbour.value.rings).length;\r\n\r\n if (nIntersections === 0 && neighbour.value.isBridge == false) {\r\n nrneighbours.push(neighbour);\r\n }\r\n }\r\n\r\n return nrneighbours;\r\n }\r\n\r\n /**\r\n * Annotaed stereochemistry information for visualization.\r\n */\r\n annotateStereochemistry() {\r\n let maxDepth = 10;\r\n\r\n // For each stereo-center\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n let vertex = this.graph.vertices[i];\r\n\r\n if (!vertex.value.isStereoCenter) {\r\n continue;\r\n }\r\n\r\n let neighbours = vertex.getNeighbours();\r\n let nNeighbours = neighbours.length;\r\n let priorities = Array(nNeighbours);\r\n\r\n for (let j = 0; j < nNeighbours; j++) {\r\n let visited = new Uint8Array(this.graph.vertices.length);\r\n let priority = Array(Array());\r\n visited[vertex.id] = 1;\r\n\r\n this.visitStereochemistry(neighbours[j], vertex.id, visited, priority, maxDepth, 0);\r\n\r\n // Sort each level according to atomic number\r\n for (let k = 0; k < priority.length; k++) {\r\n priority[k].sort(function (a, b) {\r\n return b - a\r\n });\r\n }\r\n\r\n priorities[j] = [j, priority];\r\n }\r\n\r\n let maxLevels = 0;\r\n let maxEntries = 0;\r\n for (let j = 0; j < priorities.length; j++) {\r\n if (priorities[j][1].length > maxLevels) {\r\n maxLevels = priorities[j][1].length;\r\n }\r\n\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n if (priorities[j][1][k].length > maxEntries) {\r\n maxEntries = priorities[j][1][k].length;\r\n }\r\n }\r\n }\r\n\r\n for (let j = 0; j < priorities.length; j++) {\r\n let diff = maxLevels - priorities[j][1].length;\r\n for (let k = 0; k < diff; k++) {\r\n priorities[j][1].push([]);\r\n }\r\n\r\n // Break ties by the position in the SMILES string as per specification\r\n priorities[j][1].push([neighbours[j]]);\r\n\r\n // Make all same length. Fill with zeroes.\r\n for (let k = 0; k < priorities[j][1].length; k++) {\r\n let diff = maxEntries - priorities[j][1][k].length;\r\n\r\n for (let l = 0; l < diff; l++) {\r\n priorities[j][1][k].push(0);\r\n }\r\n }\r\n }\r\n\r\n priorities.sort(function (a, b) {\r\n for (let j = 0; j < a[1].length; j++) {\r\n for (let k = 0; k < a[1][j].length; k++) {\r\n if (a[1][j][k] > b[1][j][k]) {\r\n return -1;\r\n } else if (a[1][j][k] < b[1][j][k]) {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n });\r\n\r\n let order = new Uint8Array(nNeighbours);\r\n for (let j = 0; j < nNeighbours; j++) {\r\n order[j] = priorities[j][0];\r\n vertex.value.priority = j;\r\n }\r\n\r\n // Check the angles between elements 0 and 1, and 0 and 2 to determine whether they are\r\n // drawn cw or ccw\r\n // TODO: OC(Cl)=[C@]=C(C)F currently fails here, however this is, IMHO, not a valid SMILES.\r\n let posA = this.graph.vertices[neighbours[order[0]]].position;\r\n let posB = this.graph.vertices[neighbours[order[1]]].position;\r\n\r\n let cwA = posA.relativeClockwise(posB, vertex.position);\r\n\r\n // If the second priority is clockwise from the first, the ligands are drawn clockwise, since\r\n // The hydrogen can be drawn on either side\r\n let isCw = cwA === -1;\r\n\r\n let rotation = vertex.value.bracket.chirality === '@' ? -1 : 1;\r\n let rs = MathHelper.parityOfPermutation(order) * rotation === 1 ? 'R' : 'S';\r\n\r\n // Flip the hydrogen direction when the drawing doesn't match the chirality.\r\n let wedgeA = 'down';\r\n let wedgeB = 'up';\r\n if (isCw && rs !== 'R' || !isCw && rs !== 'S') {\r\n vertex.value.hydrogenDirection = 'up';\r\n wedgeA = 'up';\r\n wedgeB = 'down';\r\n }\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, neighbours[order[order.length - 1]]).wedge = wedgeA;\r\n }\r\n\r\n // Get the shortest subtree to flip up / down. Ignore lowest priority\r\n // The rules are following:\r\n // 1. Do not draw wedge between two stereocenters\r\n // 2. Heteroatoms\r\n // 3. Draw outside ring\r\n // 4. Shortest subtree\r\n\r\n let wedgeOrder = new Array(neighbours.length - 1);\r\n let showHydrogen = vertex.value.rings.length > 1 && vertex.value.hasHydrogen;\r\n let offset = vertex.value.hasHydrogen ? 1 : 0;\r\n\r\n for (let j = 0; j < order.length - offset; j++) {\r\n wedgeOrder[j] = new Uint32Array(2);\r\n let neighbour = this.graph.vertices[neighbours[order[j]]];\r\n wedgeOrder[j][0] += neighbour.value.isStereoCenter ? 0 : 100000;\r\n // wedgeOrder[j][0] += neighbour.value.rings.length > 0 ? 0 : 10000;\r\n // Only add if in same ring, unlike above\r\n wedgeOrder[j][0] += this.areVerticesInSameRing(neighbour, vertex) ? 0 : 10000;\r\n wedgeOrder[j][0] += neighbour.value.isHeteroAtom() ? 1000 : 0;\r\n wedgeOrder[j][0] -= neighbour.value.subtreeDepth === 0 ? 1000 : 0;\r\n wedgeOrder[j][0] += 1000 - neighbour.value.subtreeDepth;\r\n wedgeOrder[j][1] = neighbours[order[j]];\r\n }\r\n\r\n\r\n wedgeOrder.sort(function (a, b) {\r\n if (a[0] > b[0]) {\r\n return -1;\r\n } else if (a[0] < b[0]) {\r\n return 1;\r\n }\r\n return 0;\r\n });\r\n\r\n // If all neighbours are in a ring, do not draw wedge, the hydrogen will be drawn.\r\n if (!showHydrogen) {\r\n let wedgeId = wedgeOrder[0][1];\r\n\r\n if (vertex.value.hasHydrogen) {\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedgeB;\r\n } else {\r\n let wedge = wedgeB;\r\n\r\n for (let j = order.length - 1; j >= 0; j--) {\r\n if (wedge === wedgeA) {\r\n wedge = wedgeB;\r\n } else {\r\n wedge = wedgeA;\r\n }\r\n if (neighbours[order[j]] === wedgeId) {\r\n break;\r\n }\r\n }\r\n\r\n this.graph.getEdge(vertex.id, wedgeId).wedge = wedge;\r\n }\r\n }\r\n\r\n vertex.value.chirality = rs;\r\n }\r\n }\r\n\r\n /**\r\n *\r\n *\r\n * @param {Number} vertexId The id of a vertex.\r\n * @param {(Number|null)} previousVertexId The id of the parent vertex of the vertex.\r\n * @param {Uint8Array} visited An array containing the visited flag for all vertices in the graph.\r\n * @param {Array} priority An array of arrays storing the atomic numbers for each level.\r\n * @param {Number} maxDepth The maximum depth.\r\n * @param {Number} depth The current depth.\r\n * @param {Number} parentAtomicNumber\r\n */\r\n visitStereochemistry(vertexId, previousVertexId, visited, priority, maxDepth, depth, parentAtomicNumber = 0) {\r\n visited[vertexId] = 1;\r\n let vertex = this.graph.vertices[vertexId];\r\n let atomicNumber = vertex.value.getAtomicNumber();\r\n\r\n if (priority.length <= depth) {\r\n priority.push(Array());\r\n }\r\n\r\n for (let i = 0; i < this.graph.getEdge(vertexId, previousVertexId).weight; i++) {\r\n priority[depth].push(parentAtomicNumber * 1000 + atomicNumber);\r\n }\r\n\r\n let neighbours = this.graph.vertices[vertexId].neighbours;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (visited[neighbours[i]] !== 1 && depth < maxDepth - 1) {\r\n this.visitStereochemistry(neighbours[i], vertexId, visited.slice(), priority, maxDepth, depth + 1, atomicNumber);\r\n }\r\n }\r\n\r\n // Valences are filled with hydrogens and passed to the next level.\r\n if (depth < maxDepth - 1) {\r\n let bonds = 0;\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n bonds += this.graph.getEdge(vertexId, neighbours[i]).weight;\r\n }\r\n\r\n for (let i = 0; i < vertex.value.getMaxBonds() - bonds; i++) {\r\n if (priority.length <= depth + 1) {\r\n priority.push(Array());\r\n }\r\n\r\n priority[depth + 1].push(atomicNumber * 1000 + 1);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Creates pseudo-elements (such as Et, Me, Ac, Bz, ...) at the position of the carbon sets\r\n * the involved atoms not to be displayed.\r\n */\r\n initPseudoElements() {\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n // Ignore atoms that have less than 3 neighbours, except if\r\n // the vertex is connected to a ring and has two neighbours\r\n if (vertex.getNeighbourCount() < 3 || vertex.value.rings.length > 0) {\r\n continue;\r\n }\r\n\r\n // TODO: This exceptions should be handled more elegantly (via config file?)\r\n\r\n // Ignore phosphates (especially for triphosphates)\r\n if (vertex.value.element === 'P') {\r\n continue;\r\n }\r\n\r\n // Ignore also guanidine\r\n if (vertex.value.element === 'C' && neighbours.length === 3 &&\r\n neighbours[0].value.element === 'N' && neighbours[1].value.element === 'N' && neighbours[2].value.element === 'N') {\r\n continue;\r\n }\r\n\r\n // Continue if there are less than two heteroatoms\r\n // or if a neighbour has more than 1 neighbour\r\n let heteroAtomCount = 0;\r\n let ctn = 0;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n let neighbouringElement = neighbour.value.element;\r\n let neighbourCount = neighbour.getNeighbourCount();\r\n\r\n if (neighbouringElement !== 'C' && neighbouringElement !== 'H' &&\r\n neighbourCount === 1) {\r\n heteroAtomCount++;\r\n }\r\n\r\n if (neighbourCount > 1) {\r\n ctn++;\r\n }\r\n }\r\n\r\n if (ctn > 1 || heteroAtomCount < 2) {\r\n continue;\r\n }\r\n\r\n // Get the previous atom (the one which is not terminal)\r\n let previous = null;\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n previous = neighbour;\r\n }\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j];\r\n\r\n if (neighbour.getNeighbourCount() > 1) {\r\n continue;\r\n }\r\n\r\n neighbour.value.isDrawn = false;\r\n\r\n let hydrogens = Atom.maxBonds[neighbour.value.element] - neighbour.value.bondCount;\r\n let charge = '';\r\n\r\n if (neighbour.value.bracket) {\r\n hydrogens = neighbour.value.bracket.hcount;\r\n charge = neighbour.value.bracket.charge || 0;\r\n }\r\n\r\n vertex.value.attachPseudoElement(neighbour.value.element, previous ? previous.value.element : null, hydrogens, charge);\r\n }\r\n }\r\n\r\n // The second pass\r\n for (let i = 0; i < this.graph.vertices.length; i++) {\r\n const vertex = this.graph.vertices[i];\r\n const atom = vertex.value;\r\n const element = atom.element;\r\n\r\n if (element === 'C' || element === 'H' || !atom.isDrawn) {\r\n continue;\r\n }\r\n\r\n const neighbourIds = vertex.neighbours;\r\n let neighbours = Array(neighbourIds.length);\r\n\r\n for (let j = 0; j < neighbourIds.length; j++) {\r\n neighbours[j] = this.graph.vertices[neighbourIds[j]];\r\n }\r\n\r\n for (let j = 0; j < neighbours.length; j++) {\r\n let neighbour = neighbours[j].value;\r\n\r\n if (!neighbour.hasAttachedPseudoElements || neighbour.getAttachedPseudoElementsCount() !== 2) {\r\n continue;\r\n }\r\n\r\n const pseudoElements = neighbour.getAttachedPseudoElements();\r\n\r\n if (pseudoElements.hasOwnProperty('0O') && pseudoElements.hasOwnProperty('3C')) {\r\n neighbour.isDrawn = false;\r\n vertex.value.attachPseudoElement('Ac', '', 0);\r\n }\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.graph.getDecays();\r\n }\r\n\r\n buildBlockSmiles() {\r\n return this.graph.buildSmiles();\r\n }\r\n\r\n /**\r\n * Find edge and mark it as decay point and redraw graph\r\n * @param e event\r\n */\r\n handleMouseClick(e) {\r\n if (this.opts.drawDecayPoints === DecayState.VALUES.NO) {\r\n return;\r\n }\r\n e.preventDefault();\r\n e.stopPropagation();\r\n if (!this.graph) {\r\n return;\r\n }\r\n this.findAndReDrawEdge(e.clientX - this.opts.offsetX, e.clientY - this.opts.offsetY + (document.documentElement.scrollTop || document.body.scrollTop));\r\n }\r\n\r\n /**\r\n * Find edge which was clicked, mark edge as decay point and redraw graph\r\n * @param mouseX mouse positionX - offsetX\r\n * @param mouseY mouse positionY - offsetY\r\n */\r\n findAndReDrawEdge(mouseX, mouseY) {\r\n for (let i = 0; i < this.graph.edges.length; ++i) {\r\n let vertexA = this.graph.vertices[this.graph.edges[i].sourceId];\r\n let vertexB = this.graph.vertices[this.graph.edges[i].targetId];\r\n if (!vertexA || !vertexB) {\r\n continue;\r\n }\r\n let scale = this.computeScale();\r\n let line = new Line(vertexA.position, vertexB.position, null, null, false, false, true);\r\n let l = this.computeEdgeLeftPoint(line, scale);\r\n let r = this.computeEdgeRightPoint(line, scale);\r\n if (mouseX < l.x - this.opts.mouseTolerance || mouseX > r.x + this.opts.mouseTolerance) {\r\n continue;\r\n }\r\n if ((mouseY > l.y - this.opts.mouseTolerance && mouseY < r.y + this.opts.mouseTolerance)\r\n || (mouseY > r.y - this.opts.mouseTolerance && mouseY < l.y + this.opts.mouseTolerance)) {\r\n this.reDrawGraphWithEdgeAsDecay(i);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Make edge decay point and redraw graph\r\n * @param {Number} edgeId\r\n */\r\n reDrawGraphWithEdgeAsDecay(edgeId) {\r\n this.graph.revertEdgeDecayPoint(edgeId);\r\n this.canvasWrapper.updateSize(this.opts.width, this.opts.height);\r\n this.canvasWrapper.scale(this.graph.vertices);\r\n this.drawEdges(this.opts.debug);\r\n this.drawVertices(this.opts.debug);\r\n this.canvasWrapper.reset();\r\n }\r\n\r\n /**\r\n * Compute scale of canvas\r\n * @return {number} scale\r\n */\r\n computeScale() {\r\n let scaleX = this.canvasWrapper.canvas.offsetWidth / this.canvasWrapper.drawingWidth;\r\n let scaleY = this.canvasWrapper.canvas.offsetHeight / this.canvasWrapper.drawingHeight;\r\n return (scaleX < scaleY) ? scaleX : scaleY;\r\n }\r\n\r\n /**\r\n * Compute left point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeLeftPoint(line, scale) {\r\n return this.computeEdgePoint(line.getLeftVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute right point of edge for compare\r\n * @param {Line} line\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgeRightPoint(line, scale) {\r\n return this.computeEdgePoint(line.getRightVector().clone(), scale);\r\n }\r\n\r\n /**\r\n * Compute point coordinates for compare\r\n * add offset to coordinates and multiply coordinates with scale\r\n * @param {Vector2} point\r\n * @param {Number} scale\r\n * @return {Vector2} point\r\n */\r\n computeEdgePoint(point, scale) {\r\n point.x += this.canvasWrapper.offsetX;\r\n point.y += this.canvasWrapper.offsetY;\r\n point.x *= scale;\r\n point.y *= scale;\r\n return point;\r\n }\r\n}\r\n\r\nmodule.exports = Drawer;\r\n","//@ts-check\r\n\r\n/** \r\n * A class representing an edge. \r\n * \r\n * @property {Number} id The id of this edge.\r\n * @property {Number} sourceId The id of the source vertex.\r\n * @property {Number} targetId The id of the target vertex.\r\n * @property {Number} weight The weight of this edge. That is, the degree of the bond (single bond = 1, double bond = 2, etc).\r\n * @property {String} [bondType='-'] The bond type of this edge.\r\n * @property {Boolean} [isPartOfAromaticRing=false] Whether or not this edge is part of an aromatic ring.\r\n * @property {Boolean} [center=false] Wheter or not the bond is centered. For example, this affects straight double bonds.\r\n * @property {String} [wedge=''] Wedge direction. Either '', 'up' or 'down'\r\n */\r\nclass Edge {\r\n /**\r\n * The constructor for the class Edge.\r\n *\r\n * @param {Number} sourceId A vertex id.\r\n * @param {Number} targetId A vertex id.\r\n * @param {Number} [weight=1] The weight of the edge.\r\n */\r\n constructor(sourceId, targetId, weight = 1) {\r\n this.id = null;\r\n this.sourceId = sourceId;\r\n this.targetId = targetId;\r\n this.weight = weight;\r\n this.bondType = '-';\r\n this.isPartOfAromaticRing = false;\r\n this.center = false;\r\n this.wedge = '';\r\n this.isDecay = false;\r\n this.isDecayAll = false;\r\n }\r\n\r\n /**\r\n * Set the bond type of this edge. This also sets the edge weight.\r\n * @param {String} bondType \r\n */\r\n setBondType(bondType) {\r\n this.bondType = bondType;\r\n this.weight = Edge.bonds[bondType];\r\n }\r\n\r\n /**\r\n * Set decay\r\n * @param {Boolean} decay point\r\n */\r\n setDecay(decay) {\r\n this.isDecay = decay;\r\n }\r\n\r\n /**\r\n * Set decay All\r\n * @param {Boolean} decay point\r\n */\r\n setDecayAll(decay) {\r\n this.isDecayAll = decay;\r\n }\r\n\r\n /**\r\n * An object mapping the bond type to the number of bonds.\r\n *\r\n * @returns {Object} The object containing the map.\r\n */\r\n static get bonds() {\r\n return {\r\n '-': 1,\r\n '/': 1,\r\n '\\\\': 1,\r\n '=': 2,\r\n '#': 3,\r\n '$': 4\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = Edge;\r\n","//@ts-check\r\nconst DecayPoint = require('./DecayPoint');\r\nconst MathHelper = require('./MathHelper');\r\nconst Vector2 = require('./Vector2');\r\nconst Vertex = require('./Vertex');\r\nconst Edge = require('./Edge');\r\nconst Ring = require('./Ring');\r\nconst Atom = require('./Atom');\r\nconst VertexState = require('./VertexState');\r\nconst SmallGraph = require('./SmallGraph');\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst DecayState = require('./DecayState');\r\nconst MutableBoolean = require('./MutableBoolean');\r\nconst MutableCounter = require('./MutableCounter');\r\nconst Direction = require('./Direction');\r\n\r\n/**\r\n * A class representing the molecular graph.\r\n *\r\n * @property {Vertex[]} vertices The vertices of the graph.\r\n * @property {Edge[]} edges The edges of this graph.\r\n * @property {Number[]} decays The id of edges marked as decay point of this graph.\r\n * @property {Object} vertexIdsToEdgeId A map mapping vertex ids to the edge between the two vertices. The key is defined as vertexAId + '_' + vertexBId.\r\n * @property {Boolean} isometric A boolean indicating whether or not the SMILES associated with this graph is isometric.\r\n */\r\nclass Graph {\r\n /**\r\n * The constructor of the class Graph.\r\n *\r\n * @param {Object} parseTree A SMILES parse tree.\r\n * @param {Boolean} [isomeric=false] A boolean specifying whether or not the SMILES is isomeric.\r\n * @param options\r\n */\r\n constructor(parseTree, isomeric = false, options = {}) {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.decays = Array();\r\n this.decaysAll = Array();\r\n this.vertexIdsToEdgeId = {};\r\n this.isomeric = isomeric;\r\n this._startingVertexes = [];\r\n this._isCyclic = false;\r\n this._polyketide = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.options = options;\r\n this._componentsIsPolyketide = [];\r\n\r\n // Used for the bridge detection algorithm\r\n this._time = 0;\r\n this._init(parseTree);\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION. Initializing the graph from the parse tree.\r\n *\r\n * @param {Object} node The current node in the parse tree.\r\n * @param order\r\n * @param {Number} parentVertexId=null The id of the previous vertex.\r\n * @param {Boolean} isBranch=false Whether or not the bond leading to this vertex is a branch bond. Branches are represented by parentheses in smiles (e.g. CC(O)C).\r\n */\r\n _init(node, order = 0, parentVertexId = null, isBranch = false) {\r\n // Create a new vertex object\r\n let atom = new Atom(node.atom.element ? node.atom.element : node.atom, node.bond);\r\n\r\n atom.branchBond = node.branchBond;\r\n atom.ringbonds = node.ringbonds;\r\n atom.bracket = node.atom.element ? node.atom : null;\r\n\r\n let vertex = new Vertex(atom);\r\n let parentVertex = this.vertices[parentVertexId];\r\n\r\n this.addVertex(vertex);\r\n\r\n // Add the id of this node to the parent as child\r\n if (parentVertexId !== null) {\r\n vertex.setParentVertexId(parentVertexId);\r\n vertex.value.addNeighbouringElement(parentVertex.value.element);\r\n parentVertex.addChild(vertex.id);\r\n parentVertex.value.addNeighbouringElement(atom.element);\r\n\r\n // In addition create a spanningTreeChildren property, which later will\r\n // not contain the children added through ringbonds\r\n parentVertex.spanningTreeChildren.push(vertex.id);\r\n\r\n // Add edge between this node and its parent\r\n let edge = new Edge(parentVertexId, vertex.id, 1);\r\n let vertexId;\r\n\r\n if (isBranch) {\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n edge.setBondType(vertex.value.branchBond || '-');\r\n vertexId = vertex.id;\r\n } else {\r\n edge.setBondType(parentVertex.value.bondType || '-');\r\n vertexId = parentVertex.id;\r\n }\r\n\r\n this.addEdge(edge);\r\n }\r\n\r\n let offset = node.ringbondCount + 1;\r\n\r\n if (atom.bracket) {\r\n offset += atom.bracket.hcount;\r\n }\r\n\r\n let stereoHydrogens = 0;\r\n if (atom.bracket && atom.bracket.chirality) {\r\n atom.isStereoCenter = true;\r\n stereoHydrogens = atom.bracket.hcount;\r\n for (var i = 0; i < stereoHydrogens; i++) {\r\n this._init({\r\n atom: 'H',\r\n isBracket: 'false',\r\n branches: Array(),\r\n branchCount: 0,\r\n ringbonds: Array(),\r\n ringbondCount: false,\r\n next: null,\r\n hasNext: false,\r\n bond: '-'\r\n }, i, vertex.id, true);\r\n }\r\n }\r\n\r\n for (var i = 0; i < node.branchCount; i++) {\r\n this._init(node.branches[i], i + offset, vertex.id, true);\r\n }\r\n\r\n if (node.hasNext) {\r\n this._init(node.next, node.branchCount + offset, vertex.id);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of molecule\r\n * Types of decay points, declared in DecayPoint\r\n */\r\n findDecayPoints() {\r\n if (!Object.keys(this.options).length) {\r\n return;\r\n }\r\n\r\n switch (this.options.drawDecayPoints) {\r\n default:\r\n case DecayState.VALUES.NO:\r\n return;\r\n case DecayState.VALUES.STANDARD:\r\n this.standardDecays();\r\n break;\r\n case DecayState.VALUES.SOURCE:\r\n this.sourceDecays();\r\n break;\r\n case DecayState.VALUES.STANDARD_AND_SOURCE:\r\n this.standardDecays();\r\n this.sourceDecays();\r\n break;\r\n }\r\n }\r\n\r\n reduceDecays() {\r\n this._decaysCopy = [];\r\n this.dfsSmilesInitialization();\r\n for (let i = 0; i < this.decays.length; i++) {\r\n this.smallBlockDfsStart(this.edges[this.decays[i]]);\r\n }\r\n this.decays = [];\r\n this.decays = this._decaysCopy;\r\n this.setStandardDecays();\r\n }\r\n\r\n dfsSmallInitialization(vertices) {\r\n for (let i = 0; i < vertices.length; ++i) {\r\n this.vertices[vertices[i]].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n smallBlockDfsStart(edge) {\r\n let stackVisitedVertexes = [];\r\n let depth = this.smallDfs(this.vertices[edge.sourceId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n stackVisitedVertexes = [];\r\n depth = this.smallDfs(this.vertices[edge.targetId], 0, stackVisitedVertexes);\r\n this.dfsSmilesInitialization();\r\n if (depth > 3) {\r\n this._decaysCopy.push(edge.id);\r\n }\r\n }\r\n }\r\n\r\n smallDfs(vertex, depth, stackVisitedVertexes) {\r\n stackVisitedVertexes.push(vertex.id);\r\n if (depth > 3) {\r\n return depth;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return depth;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n ++depth;\r\n\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n depth = this.smallDfs(this.vertices[nextVertex], depth, stackVisitedVertexes);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n return depth;\r\n }\r\n\r\n setStandardDecays() {\r\n this.edges.forEach(e => {\r\n e.setDecay(false);\r\n });\r\n this.decays.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n });\r\n }\r\n\r\n standardDecays() {\r\n for (let i = 0; i < this.edges.length; i++) {\r\n if (this.edges[i].bondType === '=') {\r\n let dec = this.isDecayPoint(this.edges[i].sourceId, this.edges[i].targetId, i);\r\n if (dec !== false) {\r\n this.edges[dec].setDecay(true);\r\n this.decays.push(dec);\r\n this.edges[dec].setDecayAll(true);\r\n this.decaysAll.push(dec);\r\n }\r\n }\r\n }\r\n this.reduceDecays();\r\n }\r\n\r\n sourceDecays() {\r\n this.options.decaySource.forEach(e => {\r\n this.edges[e].setDecay(true);\r\n this.edges[e].setDecayAll(true);\r\n this.decays.push(e);\r\n this.decaysAll.push(e);\r\n });\r\n }\r\n\r\n /**\r\n * check if its decay point of specific decay types\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @param decayTypes DecayPoint\r\n * @returns {int|boolean} return edge id when found, otherwise return false\r\n */\r\n isDecayPoint(sourceId, targetId, edgeBondId, decayTypes = DecayPoint.VALUES.ALL) {\r\n switch (decayTypes) {\r\n case DecayPoint.VALUES.ALL:\r\n let found = this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n if (found === false) {\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n } else {\r\n return found;\r\n }\r\n case DecayPoint.VALUES.COO:\r\n return this.getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId);\r\n case DecayPoint.VALUES.CONH:\r\n return this.getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId);\r\n }\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-O- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCOO(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'O', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'O', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay points of -CO-NH- type\r\n * @param sourceId\r\n * @param targetId\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayIdOfCONH(sourceId, targetId, edgeBondId) {\r\n if (this.vertices[sourceId].value.element === 'O' && this.vertices[targetId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(targetId, 'N', edgeBondId);\r\n } else if (this.vertices[targetId].value.element === 'O' && this.vertices[sourceId].value.element === 'C') {\r\n return this.getNeighbourEdgeDecayId(sourceId, 'N', edgeBondId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find decay point edge id of right neighbour\r\n * @param vertexId\r\n * @param element\r\n * @param edgeBondId\r\n * @returns {int|boolean}\r\n */\r\n getNeighbourEdgeDecayId(vertexId, element, edgeBondId) {\r\n for (let i = 0; i < this.vertices[vertexId].edges.length; i++) {\r\n let edgeId = this.checkNeighbourEdgeId(this.vertices[vertexId].edges[i], vertexId, element);\r\n if (edgeId !== false && edgeId !== edgeBondId) {\r\n return edgeId;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Find edge id of decay point\r\n * @param edgeId\r\n * @param vertexId\r\n * @param element\r\n * @returns {int|boolean}\r\n */\r\n checkNeighbourEdgeId(edgeId, vertexId, element) {\r\n if ((this.edges[edgeId].sourceId === vertexId && this.vertices[this.edges[edgeId].targetId].value.element === element) ||\r\n (this.edges[edgeId].targetId === vertexId && this.vertices[this.edges[edgeId].sourceId].value.element === element)) {\r\n return edgeId;\r\n } else {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Clears all the elements in this graph (edges and vertices).\r\n */\r\n clear() {\r\n this.vertices = Array();\r\n this.edges = Array();\r\n this.vertexIdsToEdgeId = {};\r\n }\r\n\r\n /**\r\n * Add a vertex to the graph.\r\n *\r\n * @param {Vertex} vertex A new vertex.\r\n * @returns {Number} The vertex id of the new vertex.\r\n */\r\n addVertex(vertex) {\r\n vertex.id = this.vertices.length;\r\n this.vertices.push(vertex);\r\n\r\n return vertex.id;\r\n }\r\n\r\n /**\r\n * Add an edge to the graph.\r\n *\r\n * @param {Edge} edge A new edge.\r\n * @returns {Number} The edge id of the new edge.\r\n */\r\n addEdge(edge) {\r\n let source = this.vertices[edge.sourceId];\r\n let target = this.vertices[edge.targetId];\r\n\r\n edge.id = this.edges.length;\r\n this.edges.push(edge);\r\n\r\n this.vertexIdsToEdgeId[edge.sourceId + '_' + edge.targetId] = edge.id;\r\n this.vertexIdsToEdgeId[edge.targetId + '_' + edge.sourceId] = edge.id;\r\n edge.isPartOfAromaticRing = source.value.isPartOfAromaticRing && target.value.isPartOfAromaticRing;\r\n\r\n source.value.bondCount += edge.weight;\r\n target.value.bondCount += edge.weight;\r\n\r\n source.edges.push(edge.id);\r\n target.edges.push(edge.id);\r\n\r\n return edge.id;\r\n }\r\n\r\n /**\r\n * Returns the edge between two given vertices.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {(Edge|null)} The edge or, if no edge can be found, null.\r\n */\r\n getEdge(vertexIdA, vertexIdB) {\r\n let edgeId = this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB];\r\n\r\n return edgeId === undefined ? null : this.edges[edgeId];\r\n }\r\n\r\n /**\r\n * Returns the ids of edges connected to a vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Number[]} An array containing the ids of edges connected to the vertex.\r\n */\r\n getEdges(vertexId) {\r\n let edgeIds = Array();\r\n let vertex = this.vertices[vertexId];\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n edgeIds.push(this.vertexIdsToEdgeId[vertexId + '_' + vertex.neighbours[i]]);\r\n }\r\n\r\n return edgeIds;\r\n }\r\n\r\n\r\n /**\r\n * Check whether or not two vertices are connected by an edge.\r\n *\r\n * @param {Number} vertexIdA A vertex id.\r\n * @param {Number} vertexIdB A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not two vertices are connected by an edge.\r\n */\r\n hasEdge(vertexIdA, vertexIdB) {\r\n return this.vertexIdsToEdgeId[vertexIdA + '_' + vertexIdB] !== undefined\r\n }\r\n\r\n /**\r\n * Returns an array containing the vertex ids of this graph.\r\n *\r\n * @returns {Number[]} An array containing all vertex ids of this graph.\r\n */\r\n getVertexList() {\r\n let arr = [this.vertices.length];\r\n\r\n for (var i = 0; i < this.vertices.length; i++) {\r\n arr[i] = this.vertices[i].id;\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array containing source, target arrays of this graphs edges.\r\n *\r\n * @returns {Array[]} An array containing source, target arrays of this graphs edges. Example: [ [ 2, 5 ], [ 6, 9 ] ].\r\n */\r\n getEdgeList() {\r\n let arr = Array(this.edges.length);\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n arr[i] = [this.edges[i].sourceId, this.edges[i].targetId];\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph.\r\n */\r\n getAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of the graph with all bridges removed (thus the components). Thus the remaining vertices are all part of ring systems.\r\n *\r\n * @returns {Array[]} The adjancency matrix of the molecular graph with all bridges removed.\r\n */\r\n getComponentsAdjacencyMatrix() {\r\n let length = this.vertices.length;\r\n let adjacencyMatrix = Array(length);\r\n let bridges = this.getBridges();\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n }\r\n\r\n for (var i = 0; i < this.edges.length; i++) {\r\n let edge = this.edges[i];\r\n\r\n adjacencyMatrix[edge.sourceId][edge.targetId] = 1;\r\n adjacencyMatrix[edge.targetId][edge.sourceId] = 1;\r\n }\r\n\r\n for (var i = 0; i < bridges.length; i++) {\r\n adjacencyMatrix[bridges[i][0]][bridges[i][1]] = 0;\r\n adjacencyMatrix[bridges[i][1]][bridges[i][0]] = 0;\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the adjacency matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency matrix of the subgraph.\r\n */\r\n getSubgraphAdjacencyMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyMatrix = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyMatrix[i] = new Array(length);\r\n adjacencyMatrix[i].fill(0);\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyMatrix[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n return adjacencyMatrix;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of the graph.\r\n *\r\n * @returns {Array[]} The distance matrix of the graph.\r\n */\r\n getDistanceMatrix() {\r\n let length = this.vertices.length;\r\n let adja = this.getAdjacencyMatrix();\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the distance matrix of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The distance matrix of the subgraph.\r\n */\r\n getSubgraphDistanceMatrix(vertexIds) {\r\n let length = vertexIds.length;\r\n let adja = this.getSubgraphAdjacencyMatrix(vertexIds);\r\n let dist = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n dist[i] = Array(length);\r\n dist[i].fill(Infinity);\r\n }\r\n\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (adja[i][j] === 1) {\r\n dist[i][j] = 1;\r\n }\r\n }\r\n }\r\n\r\n for (var k = 0; k < length; k++) {\r\n for (var i = 0; i < length; i++) {\r\n for (var j = 0; j < length; j++) {\r\n if (dist[i][j] > dist[i][k] + dist[k][j]) {\r\n dist[i][j] = dist[i][k] + dist[k][j]\r\n }\r\n }\r\n }\r\n }\r\n\r\n return dist;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of the graph.\r\n *\r\n * @returns {Array[]} The adjancency list of the graph.\r\n */\r\n getAdjacencyList() {\r\n let length = this.vertices.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = [];\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(this.vertices[i].id, this.vertices[j].id)) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Get the adjacency list of a subgraph.\r\n *\r\n * @param {Number[]} vertexIds An array containing the vertex ids contained within the subgraph.\r\n * @returns {Array[]} The adjancency list of the subgraph.\r\n */\r\n getSubgraphAdjacencyList(vertexIds) {\r\n let length = vertexIds.length;\r\n let adjacencyList = Array(length);\r\n\r\n for (var i = 0; i < length; i++) {\r\n adjacencyList[i] = Array();\r\n\r\n for (var j = 0; j < length; j++) {\r\n if (i === j) {\r\n continue;\r\n }\r\n\r\n if (this.hasEdge(vertexIds[i], vertexIds[j])) {\r\n adjacencyList[i].push(j);\r\n }\r\n }\r\n }\r\n\r\n return adjacencyList;\r\n }\r\n\r\n /**\r\n * Returns an array containing the edge ids of bridges. A bridge splits the graph into multiple components when removed.\r\n *\r\n * @returns {Number[]} An array containing the edge ids of the bridges.\r\n */\r\n getBridges() {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n let disc = new Array(length);\r\n let low = new Array(length);\r\n let parent = new Array(length);\r\n let adj = this.getAdjacencyList();\r\n let outBridges = Array();\r\n\r\n visited.fill(false);\r\n parent.fill(null);\r\n this._time = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n if (!visited[i]) {\r\n this._bridgeDfs(i, visited, disc, low, parent, adj, outBridges);\r\n }\r\n }\r\n\r\n return outBridges;\r\n }\r\n\r\n /**\r\n * Traverses the graph in breadth-first order.\r\n *\r\n * @param {Number} startVertexId The id of the starting vertex.\r\n * @param {Function} callback The callback function to be called on every vertex.\r\n */\r\n traverseBF(startVertexId, callback) {\r\n let length = this.vertices.length;\r\n let visited = new Array(length);\r\n\r\n visited.fill(false);\r\n\r\n var queue = [startVertexId];\r\n\r\n while (queue.length > 0) {\r\n // JavaScripts shift() is O(n) ... bad JavaScript, bad!\r\n let u = queue.shift();\r\n let vertex = this.vertices[u];\r\n\r\n callback(vertex);\r\n\r\n for (var i = 0; i < vertex.neighbours.length; i++) {\r\n let v = vertex.neighbours[i];\r\n if (!visited[v]) {\r\n visited[v] = true;\r\n queue.push(v);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Get the depth of a subtree in the direction opposite to the vertex specified as the parent vertex.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId The id of a neighbouring vertex.\r\n * @returns {Number} The depth of the sub-tree.\r\n */\r\n getTreeDepth(vertexId, parentVertexId) {\r\n if (vertexId === null || parentVertexId === null) {\r\n return 0;\r\n }\r\n\r\n let neighbours = this.vertices[vertexId].getSpanningTreeNeighbours(parentVertexId);\r\n let max = 0;\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n let childId = neighbours[i];\r\n let d = this.getTreeDepth(childId, vertexId);\r\n\r\n if (d > max) {\r\n max = d;\r\n }\r\n }\r\n\r\n return max + 1;\r\n }\r\n\r\n /**\r\n * Traverse a sub-tree in the graph.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @param {Number} parentVertexId A neighbouring vertex.\r\n * @param {Function} callback The callback function that is called with each visited as an argument.\r\n * @param {Number} [maxDepth=999999] The maximum depth of the recursion.\r\n * @param {Boolean} [ignoreFirst=false] Whether or not to ignore the starting vertex supplied as vertexId in the callback.\r\n * @param {Number} [depth=1] The current depth in the tree.\r\n * @param {Uint8Array} [visited=null] An array holding a flag on whether or not a node has been visited.\r\n */\r\n traverseTree(vertexId, parentVertexId, callback, maxDepth = 999999, ignoreFirst = false, depth = 1, visited = null) {\r\n if (visited === null) {\r\n visited = new Uint8Array(this.vertices.length);\r\n }\r\n\r\n if (depth > maxDepth + 1 || visited[vertexId] === 1) {\r\n return;\r\n }\r\n\r\n visited[vertexId] = 1;\r\n\r\n let vertex = this.vertices[vertexId];\r\n let neighbours = vertex.getNeighbours(parentVertexId);\r\n\r\n if (!ignoreFirst || depth > 1) {\r\n callback(vertex);\r\n }\r\n\r\n for (var i = 0; i < neighbours.length; i++) {\r\n this.traverseTree(neighbours[i], vertexId, callback, maxDepth, ignoreFirst, depth + 1, visited);\r\n }\r\n }\r\n\r\n /**\r\n * Positiones the (sub)graph using Kamada and Kawais algorithm for drawing general undirected graphs. https://pdfs.semanticscholar.org/b8d3/bca50ccc573c5cb99f7d201e8acce6618f04.pdf\r\n * There are undocumented layout parameters. They are undocumented for a reason, so be very careful.\r\n *\r\n * @param {Number[]} vertexIds An array containing vertexIds to be placed using the force based layout.\r\n * @param {Vector2} center The center of the layout.\r\n * @param {Number} startVertexId A vertex id. Should be the starting vertex - e.g. the first to be positioned and connected to a previously place vertex.\r\n * @param {Ring} ring The bridged ring associated with this force-based layout.\r\n */\r\n kkLayout(vertexIds, center, startVertexId, ring, bondLength,\r\n threshold = 0.1, innerThreshold = 0.1, maxIteration = 2000,\r\n maxInnerIteration = 50, maxEnergy = 1e9) {\r\n\r\n let edgeStrength = bondLength;\r\n\r\n // Add vertices that are directly connected to the ring\r\n var i = vertexIds.length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n var j = vertex.neighbours.length;\r\n }\r\n\r\n let matDist = this.getSubgraphDistanceMatrix(vertexIds);\r\n let length = vertexIds.length;\r\n\r\n // Initialize the positions. Place all vertices on a ring around the center\r\n let radius = MathHelper.polyCircumradius(500, length);\r\n let angle = MathHelper.centralAngle(length);\r\n let a = 0.0;\r\n let arrPositionX = new Float32Array(length);\r\n let arrPositionY = new Float32Array(length);\r\n let arrPositioned = Array(length);\r\n\r\n i = length;\r\n while (i--) {\r\n let vertex = this.vertices[vertexIds[i]];\r\n if (!vertex.positioned) {\r\n arrPositionX[i] = center.x + Math.cos(a) * radius;\r\n arrPositionY[i] = center.y + Math.sin(a) * radius;\r\n } else {\r\n arrPositionX[i] = vertex.position.x;\r\n arrPositionY[i] = vertex.position.y;\r\n }\r\n arrPositioned[i] = vertex.positioned;\r\n a += angle;\r\n }\r\n\r\n // Create the matrix containing the lengths\r\n let matLength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matLength[i] = new Array(length);\r\n var j = length;\r\n while (j--) {\r\n matLength[i][j] = bondLength * matDist[i][j];\r\n }\r\n }\r\n\r\n // Create the matrix containing the spring strenghts\r\n let matStrength = Array(length);\r\n i = length;\r\n while (i--) {\r\n matStrength[i] = Array(length);\r\n var j = length;\r\n while (j--) {\r\n matStrength[i][j] = edgeStrength * Math.pow(matDist[i][j], -2.0);\r\n }\r\n }\r\n\r\n // Create the matrix containing the energies\r\n let matEnergy = Array(length);\r\n let arrEnergySumX = new Float32Array(length);\r\n let arrEnergySumY = new Float32Array(length);\r\n i = length;\r\n while (i--) {\r\n matEnergy[i] = Array(length);\r\n }\r\n\r\n i = length;\r\n let ux, uy, dEx, dEy, vx, vy, denom;\r\n\r\n while (i--) {\r\n ux = arrPositionX[i];\r\n uy = arrPositionY[i];\r\n dEx = 0.0;\r\n dEy = 0.0;\r\n let j = length;\r\n while (j--) {\r\n if (i === j) {\r\n continue;\r\n }\r\n vx = arrPositionX[j];\r\n vy = arrPositionY[j];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n matEnergy[i][j] = [\r\n matStrength[i][j] * ((ux - vx) - matLength[i][j] * (ux - vx) * denom),\r\n matStrength[i][j] * ((uy - vy) - matLength[i][j] * (uy - vy) * denom)\r\n ];\r\n matEnergy[j][i] = matEnergy[i][j];\r\n dEx += matEnergy[i][j][0];\r\n dEy += matEnergy[i][j][1];\r\n }\r\n arrEnergySumX[i] = dEx;\r\n arrEnergySumY[i] = dEy;\r\n }\r\n\r\n // Utility functions, maybe inline them later\r\n let energy = function (index) {\r\n return [arrEnergySumX[index] * arrEnergySumX[index] + arrEnergySumY[index] * arrEnergySumY[index], arrEnergySumX[index], arrEnergySumY[index]];\r\n };\r\n\r\n let highestEnergy = function () {\r\n let maxEnergy = 0.0;\r\n let maxEnergyId = 0;\r\n let maxDEX = 0.0;\r\n let maxDEY = 0.0;\r\n\r\n i = length;\r\n while (i--) {\r\n let [delta, dEX, dEY] = energy(i);\r\n\r\n if (delta > maxEnergy && arrPositioned[i] === false) {\r\n maxEnergy = delta;\r\n maxEnergyId = i;\r\n maxDEX = dEX;\r\n maxDEY = dEY;\r\n }\r\n }\r\n\r\n return [maxEnergyId, maxEnergy, maxDEX, maxDEY];\r\n };\r\n\r\n let update = function (index, dEX, dEY) {\r\n let dxx = 0.0;\r\n let dyy = 0.0;\r\n let dxy = 0.0;\r\n let ux = arrPositionX[index];\r\n let uy = arrPositionY[index];\r\n let arrL = matLength[index];\r\n let arrK = matStrength[index];\r\n\r\n i = length;\r\n while (i--) {\r\n if (i === index) {\r\n continue;\r\n }\r\n\r\n let vx = arrPositionX[i];\r\n let vy = arrPositionY[i];\r\n let l = arrL[i];\r\n let k = arrK[i];\r\n let m = (ux - vx) * (ux - vx);\r\n let denom = 1.0 / Math.pow(m + (uy - vy) * (uy - vy), 1.5);\r\n\r\n dxx += k * (1 - l * (uy - vy) * (uy - vy) * denom);\r\n dyy += k * (1 - l * m * denom);\r\n dxy += k * (l * (ux - vx) * (uy - vy) * denom);\r\n }\r\n\r\n // Prevent division by zero\r\n if (dxx === 0) {\r\n dxx = 0.1;\r\n }\r\n\r\n if (dyy === 0) {\r\n dyy = 0.1;\r\n }\r\n\r\n if (dxy === 0) {\r\n dxy = 0.1;\r\n }\r\n\r\n let dy = (dEX / dxx + dEY / dxy);\r\n dy /= (dxy / dxx - dyy / dxy); // had to split this onto two lines because the syntax highlighter went crazy.\r\n let dx = -(dxy * dy + dEX) / dxx;\r\n\r\n arrPositionX[index] += dx;\r\n arrPositionY[index] += dy;\r\n\r\n // Update the energies\r\n let arrE = matEnergy[index];\r\n dEX = 0.0;\r\n dEY = 0.0;\r\n\r\n ux = arrPositionX[index];\r\n uy = arrPositionY[index];\r\n\r\n let vx, vy, prevEx, prevEy, denom;\r\n\r\n i = length;\r\n while (i--) {\r\n if (index === i) {\r\n continue;\r\n }\r\n vx = arrPositionX[i];\r\n vy = arrPositionY[i];\r\n // Store old energies\r\n prevEx = arrE[i][0];\r\n prevEy = arrE[i][1];\r\n denom = 1.0 / Math.sqrt((ux - vx) * (ux - vx) + (uy - vy) * (uy - vy));\r\n dx = arrK[i] * ((ux - vx) - arrL[i] * (ux - vx) * denom);\r\n dy = arrK[i] * ((uy - vy) - arrL[i] * (uy - vy) * denom);\r\n\r\n arrE[i] = [dx, dy];\r\n dEX += dx;\r\n dEY += dy;\r\n arrEnergySumX[i] += dx - prevEx;\r\n arrEnergySumY[i] += dy - prevEy;\r\n }\r\n arrEnergySumX[index] = dEX;\r\n arrEnergySumY[index] = dEY;\r\n };\r\n\r\n // Setting up variables for the while loops\r\n let maxEnergyId = 0;\r\n let dEX = 0.0;\r\n let dEY = 0.0;\r\n let delta = 0.0;\r\n let iteration = 0;\r\n let innerIteration = 0;\r\n\r\n while (maxEnergy > threshold && maxIteration > iteration) {\r\n iteration++;\r\n [maxEnergyId, maxEnergy, dEX, dEY] = highestEnergy();\r\n delta = maxEnergy;\r\n innerIteration = 0;\r\n while (delta > innerThreshold && maxInnerIteration > innerIteration) {\r\n innerIteration++;\r\n update(maxEnergyId, dEX, dEY);\r\n [delta, dEX, dEY] = energy(maxEnergyId);\r\n }\r\n }\r\n\r\n i = length;\r\n while (i--) {\r\n let index = vertexIds[i];\r\n let vertex = this.vertices[index];\r\n vertex.position.x = arrPositionX[i];\r\n vertex.position.y = arrPositionY[i];\r\n vertex.positioned = true;\r\n vertex.forcePositioned = true;\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getBridges().\r\n */\r\n _bridgeDfs(u, visited, disc, low, parent, adj, outBridges) {\r\n visited[u] = true;\r\n disc[u] = low[u] = ++this._time;\r\n\r\n for (var i = 0; i < adj[u].length; i++) {\r\n let v = adj[u][i];\r\n\r\n if (!visited[v]) {\r\n parent[v] = u;\r\n\r\n this._bridgeDfs(v, visited, disc, low, parent, adj, outBridges);\r\n\r\n low[u] = Math.min(low[u], low[v]);\r\n\r\n // If low > disc, we have a bridge\r\n if (low[v] > disc[u]) {\r\n outBridges.push([u, v]);\r\n }\r\n } else if (v !== parent[u]) {\r\n low[u] = Math.min(low[u], disc[v]);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the connected components of the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Set[]} Connected components as sets.\r\n */\r\n static getConnectedComponents(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let components = [];\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n let component = Array();\r\n visited[u] = true;\r\n component.push(u);\r\n count++;\r\n Graph._ccGetDfs(u, visited, adjacencyMatrix, component);\r\n if (component.length > 1) {\r\n components.push(component);\r\n }\r\n }\r\n }\r\n\r\n return components;\r\n }\r\n\r\n /**\r\n * Returns the number of connected components for the graph.\r\n *\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of connected components of the supplied graph.\r\n */\r\n static getConnectedComponentCount(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let visited = new Array(length);\r\n let count = 0;\r\n\r\n visited.fill(false);\r\n\r\n for (var u = 0; u < length; u++) {\r\n if (!visited[u]) {\r\n visited[u] = true;\r\n count++;\r\n Graph._ccCountDfs(u, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n return count;\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponentCount().\r\n */\r\n static _ccCountDfs(u, visited, adjacencyMatrix) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n Graph._ccCountDfs(v, visited, adjacencyMatrix);\r\n }\r\n }\r\n\r\n /**\r\n * PRIVATE FUNCTION used by getConnectedComponents().\r\n */\r\n static _ccGetDfs(u, visited, adjacencyMatrix, component) {\r\n for (var v = 0; v < adjacencyMatrix[u].length; v++) {\r\n let c = adjacencyMatrix[u][v];\r\n\r\n if (!c || visited[v] || u === v) {\r\n continue;\r\n }\r\n\r\n visited[v] = true;\r\n component.push(v);\r\n Graph._ccGetDfs(v, visited, adjacencyMatrix, component);\r\n }\r\n }\r\n\r\n /**\r\n * Revert decay point value and update list of decay points\r\n * when edge isn't decay point -> change mark edge as decay point and add edge to decays list\r\n * when edge is decay point -> unmark edge as decay point and remove edgeId from list of decays\r\n * @param edgeId\r\n */\r\n revertEdgeDecayPoint(edgeId) {\r\n this.edges[edgeId].isDecay = !this.edges[edgeId].isDecay;\r\n this.edges[edgeId].isDecayAll = !this.edges[edgeId].isDecayAll;\r\n if (this.edges[edgeId].isDecay) {\r\n this.decays.push(edgeId);\r\n this.decaysAll.push(edgeId);\r\n } else {\r\n let index = this.decays.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decays.splice(index, 1);\r\n }\r\n index = this.decaysAll.indexOf(edgeId);\r\n if (index > -1) {\r\n this.decaysAll.splice(index, 1);\r\n }\r\n }\r\n }\r\n\r\n getDecays() {\r\n return this.decays;\r\n }\r\n\r\n /**\r\n * Build block of SMILES based on decay points\r\n * DFS pass through graph\r\n * but the numbers are already setup in vertex.value.ringbonds array so no need to second pass of dfs\r\n */\r\n buildSmiles() {\r\n let smiles = [];\r\n this._polyketide = false;\r\n this.dfsSmilesInitialization();\r\n if (this.decays.length === 0) {\r\n this.startDfs(this.vertices[0], smiles);\r\n return {blockSmiles: smiles, sequence: '[0]', sequenceType: SequenceType.VALUES.OTHER, decays: this.decays, isPolyketide: this._polyketide};\r\n } else {\r\n this.dfsBuildSmilesStart(smiles);\r\n }\r\n this.dfsSmilesInitialization();\r\n this.dfsSmallStart();\r\n this._smallGraph.oneCyclic();\r\n this._smallGraph.dfsSequenceStart();\r\n let sequenceData = this.sortSequence(smiles, this._smallGraph.sequence);\r\n return {\r\n blockSmiles: sequenceData.smiles,\r\n sequence: sequenceData.sequence,\r\n sequenceType: this._smallGraph.sequenceType + ((this._smallGraph.sequenceType === 'linear' || this._smallGraph.sequenceType === 'cyclic') && this._polyketide ? '-polyketide' : ''),\r\n decays: this.decays,\r\n isPolyketide: this._polyketide\r\n }\r\n }\r\n\r\n sortSequence(smiles, sequence) {\r\n let permutation = this.getSequencePermutation(sequence);\r\n let newSmiles = new Array(permutation.length).fill(null);\r\n for (let i = 0; i < permutation.length; ++i) {\r\n newSmiles[i] = smiles[permutation[i][0]];\r\n }\r\n\r\n let position = 0;\r\n let char = sequence.charAt(position);\r\n let newSequence = '';\r\n while (true) {\r\n switch (char) {\r\n case '0':\r\n case '1':\r\n case '2':\r\n case '3':\r\n case '4':\r\n case '5':\r\n case '6':\r\n case '7':\r\n case '8':\r\n case '9':\r\n let number = char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n while(!isNaN(char)) {\r\n number += char;\r\n ++position;\r\n if (position >= sequence.length) {\r\n return {sequence: sequence, smiles: smiles};\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n let j;\r\n for (j = 0; j < permutation.length; ++j) {\r\n if (permutation[j][0] === number) {\r\n newSequence += j;\r\n break;\r\n }\r\n }\r\n continue;\r\n default:\r\n newSequence += char;\r\n }\r\n\r\n ++position;\r\n if (position >= sequence.length) {\r\n break;\r\n }\r\n char = sequence.charAt(position);\r\n }\r\n return {sequence: newSequence, smiles: newSmiles};\r\n }\r\n\r\n getSequencePermutation(sequence) {\r\n let re = /\\d+/g;\r\n let match = null;\r\n let permutation = [];\r\n while ((match = re.exec(sequence)) != null) {\r\n permutation.push(match);\r\n }\r\n return permutation;\r\n }\r\n\r\n dfsSmallStart() {\r\n this._smallGraph = new SmallGraph();\r\n for (let index = 0; index < this._startingVertexes.length; ++index) {\r\n this._smallGraph.addVertex(new Node(this._startingVertexes[index].component));\r\n this.first = this._startingVertexes[index];\r\n this.dfsSmall(this._startingVertexes[index], this._componentsIsPolyketide[index]);\r\n }\r\n }\r\n\r\n /**\r\n * Initialize graph for dfs\r\n * set for all vertices vertexState to NotFound\r\n */\r\n dfsSmilesInitialization() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n\r\n /**\r\n * Starting function for DFS\r\n * starts on decay points (on edge), so start on both side of edge\r\n * @param {Array} smiles output param, array of SMILES blocks (string)\r\n */\r\n dfsBuildSmilesStart(smiles) {\r\n this._cnt = 0;\r\n this._markComponent = false;\r\n this._startingVertexes = [];\r\n for (let i = 0; i < this.decays.length; ++i) {\r\n let edge = this.edges[this.decays[i]];\r\n this.markingComponents(this.startDfs(this.vertices[edge.sourceId], smiles));\r\n this.markingComponents(this.startDfs(this.vertices[edge.targetId], smiles));\r\n }\r\n }\r\n\r\n markingComponents(isPolyketyde) {\r\n if (this._markComponent) {\r\n this._cnt++;\r\n this._markComponent = false;\r\n this._componentsIsPolyketide.push(isPolyketyde);\r\n }\r\n }\r\n\r\n /**\r\n * Start DFS for build SMILES of blocks\r\n * @param {Vertex} vertex to start DFS\r\n * @param {Array} smiles output param, array od SMILES\r\n */\r\n startDfs(vertex, smiles) {\r\n let isPolyketide = new MutableBoolean(true);\r\n let decaysCounter = new MutableCounter();\r\n let vertexCounter = new MutableCounter();\r\n let through = [];\r\n let stackSmiles = [];\r\n this.first = vertex.id;\r\n this._isCyclic = false;\r\n this._digitCounter = 1;\r\n this._printedDigits = [];\r\n this.dfsSmiles(vertex, stackSmiles, isPolyketide, decaysCounter, through, vertexCounter);\r\n if (decaysCounter.getValue() < 2 && isPolyketide.getValue() === true) {\r\n isPolyketide.setValue(through.every(vertex => vertex === 'O' || vertex === 'N') && vertexCounter.getValue() > 4);\r\n }\r\n if (this._isCyclic) {\r\n this.closedToNotFound();\r\n stackSmiles = [];\r\n this.dfsSmiles(vertex, stackSmiles, new MutableBoolean(true), new MutableCounter(), [], new MutableCounter(), -1, true);\r\n }\r\n this.closedToFullyClosed();\r\n\r\n stackSmiles = Graph.removeUnnecessaryParentheses(stackSmiles);\r\n let smile = Graph.removeUnnecessaryNumbers(stackSmiles.join(\"\"));\r\n if (smile.length !== 0) {\r\n smiles.push({smiles: smile, isPolyketide: isPolyketide.getValue()});\r\n if (isPolyketide.getValue() === true) {\r\n this._polyketide = true;\r\n }\r\n }\r\n return isPolyketide.getValue();\r\n }\r\n\r\n closedToNotFound() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n }\r\n }\r\n\r\n closedToFullyClosed() {\r\n for (let i = 0; i < this.vertices.length; ++i) {\r\n if (this.vertices[i].vertexState === VertexState.VALUES.CLOSED) {\r\n this.vertices[i].vertexState = VertexState.VALUES.FULLY_CLOSED;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * DFS for SMILES\r\n * @param {Vertex} vertex\r\n * @param {Array} stackSmiles output param\r\n * @param {MutableBoolean} isPolyketide\r\n * @param {MutableCounter} cntDecays\r\n * @param {Array} through\r\n * @param {MutableCounter} vertexCounter\r\n * @param lastVertexId last vertex id for setup digits\r\n * @param isSecondPass is second pass of dfs\r\n */\r\n dfsSmiles(vertex, stackSmiles, isPolyketide, cntDecays, through, vertexCounter, lastVertexId = -1, isSecondPass = false) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN && !isSecondPass && lastVertexId !== -1) {\r\n this._isCyclic = true;\r\n if (!vertex.digits.some(e => this.vertices[lastVertexId].digits.includes(e))) {\r\n vertex.digits.push(this._digitCounter);\r\n this.vertices[lastVertexId].digits.push(this._digitCounter);\r\n this._digitCounter++;\r\n }\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n if (vertex.value.element === 'H') {\r\n return;\r\n }\r\n\r\n if (this.first === vertex.id && vertex.value.element === \"C\" && isPolyketide.getValue()) {\r\n stackSmiles.push(\"O\");\r\n isPolyketide.setValue(false);\r\n }\r\n\r\n if (vertex.value.bracket) {\r\n stackSmiles.push(\"[\");\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n if (vertex.value.bracket.hcount > 0) {\r\n stackSmiles.push('H');\r\n if (vertex.value.bracket.hcount > 1) {\r\n stackSmiles.push(vertex.value.bracket.hcount);\r\n }\r\n }\r\n if (vertex.value.bracket.charge > 0) {\r\n stackSmiles.push('+');\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n } else if (vertex.value.bracket.charge < 0) {\r\n stackSmiles.push(vertex.value.bracket.charge);\r\n }\r\n stackSmiles.push(\"]\");\r\n } else {\r\n Graph.printVertexValue(stackSmiles, vertex);\r\n }\r\n vertexCounter.increment();\r\n\r\n if (isSecondPass) {\r\n stackSmiles.push(this.smilesNumbersAdd(vertex));\r\n }\r\n\r\n if (!this._markComponent) {\r\n this._startingVertexes.push(vertex);\r\n }\r\n vertex.component = this._cnt;\r\n this._markComponent = true;\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n if (edge.isDecayAll && lastVertexId !== nextVertex) {\r\n through.push(vertex.value.element);\r\n }\r\n if (edge.isDecay) {\r\n cntDecays.increment();\r\n if (vertex.value.element === \"C\" && vertex.id !== this.first && isPolyketide.getValue()) {\r\n stackSmiles.push(\"(\");\r\n stackSmiles.push(\"O\");\r\n stackSmiles.push(\")\");\r\n isPolyketide.setValue(false);\r\n }\r\n continue;\r\n }\r\n stackSmiles.push(\"(\");\r\n Graph.addBondTypeToStack(edge, stackSmiles);\r\n if (lastVertexId !== nextVertex) {\r\n this.dfsSmiles(this.vertices[nextVertex], stackSmiles, isPolyketide, cntDecays, through, vertexCounter, vertex.id, isSecondPass);\r\n }\r\n Graph.checkStack(stackSmiles);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSmall(vertex, isPolyketide) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.edges.length; ++i) {\r\n let edge = this.edges[vertex.edges[i]];\r\n if (edge.isDecay) {\r\n\r\n this._smallGraph.addNeighbour(vertex.component, this.vertices[Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId)].component, Direction.getProperValue(isPolyketide, vertex.value.element, vertex.id, this.first));\r\n continue;\r\n }\r\n let nextVertex = Graph.getProperVertex(vertex.id, edge.sourceId, edge.targetId);\r\n this.dfsSmall(this.vertices[nextVertex], isPolyketide);\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n\r\n static printVertexValue(stackSmiles, vertex) {\r\n if (vertex.value.isPartOfAromaticRing) {\r\n stackSmiles.push(vertex.value.element.toLowerCase());\r\n } else {\r\n stackSmiles.push(vertex.value.element);\r\n }\r\n }\r\n\r\n /**\r\n * Remove numbers which is neighbours in SMILES notation -> need to perform in cyclic structures\r\n * @param {String} smiles SMILES\r\n * @return {String} repaired SMILES\r\n */\r\n static removeUnnecessaryNumbers(smiles) {\r\n if (smiles === null) {\r\n return '';\r\n }\r\n try {\r\n let numbers = this.getNumbers(smiles);\r\n for (let number of numbers) {\r\n let first = this.findFirst(smiles, number);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n let tmpRange = this.removeRangeLast(smiles, first, second, number);\r\n smiles = this.repairSmiles(smiles, tmpRange, first, second, number);\r\n }\r\n return smiles;\r\n } catch (ex) {\r\n return smiles;\r\n }\r\n }\r\n\r\n /**\r\n * Remove unnecessary numbers from SMILES\r\n * @param {String} smiles\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {*}\r\n */\r\n static removeNumbers(smiles, first, second, number) {\r\n if (number > 9) {\r\n let numLength = number.toString().length;\r\n smiles = smiles.slice(0, first - 1) + smiles.slice(first + numLength);\r\n return smiles.slice(0, second - 2 - numLength) + smiles.slice(second - 1);\r\n } else {\r\n smiles = smiles.slice(0, first) + smiles.slice(first + 1);\r\n return smiles.slice(0, second - 1) + smiles.slice(second);\r\n }\r\n }\r\n\r\n /**\r\n * Reapair SMILES\r\n * @param {String} smiles\r\n * @param {String} tmpRange\r\n * @param {Number} first\r\n * @param {Number} second\r\n * @param {Number} number\r\n * @return {String|*}\r\n */\r\n static repairSmiles(smiles, tmpRange, first, second, number) {\r\n let pattern = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])$\");\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let patternOrg = new RegExp(\"^(Br|Cl|[BCNOPSFIbcnopsfi])\");\r\n if (patternOrg.test(tmpRange)) {\r\n return smiles;\r\n }\r\n\r\n while (tmpRange.length !== 0) {\r\n if (tmpRange[0] === '(') {\r\n tmpRange = tmpRange.substring(1);\r\n if (pattern.test(tmpRange)) {\r\n return this.removeNumbers(smiles, first, second, number);\r\n }\r\n let leftBrackets = 1;\r\n let rightBrackets = 0;\r\n while (leftBrackets !== rightBrackets) {\r\n switch (tmpRange[0]) {\r\n case '(':\r\n leftBrackets++;\r\n break;\r\n case ')':\r\n rightBrackets++;\r\n break;\r\n }\r\n if (\"\" === tmpRange) {\r\n return smiles;\r\n }\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n return this.repairSmiles(smiles, tmpRange, first, second, number);\r\n } else {\r\n tmpRange = tmpRange.substring(1);\r\n }\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Substring in range and remove last Organic Subset\r\n * @param smiles\r\n * @param first\r\n * @param second\r\n * @param number\r\n * @return {string}\r\n */\r\n static removeRangeLast(smiles, first, second, number) {\r\n if (number > 9) {\r\n return smiles.substring(first + number.toString().length, second - 1);\r\n } else {\r\n return smiles.substring(first + 1, second);\r\n }\r\n }\r\n\r\n /**\r\n * Get numbers from SMILES\r\n * @param smiles\r\n * @return {Set}\r\n */\r\n static getNumbers(smiles) {\r\n let numbers = new Set();\r\n for (let index = 0; index < smiles.length; ++index) {\r\n if (!isNaN(smiles[index])) {\r\n numbers.add(smiles[index]);\r\n } else if (smiles[index] === '%') {\r\n index++;\r\n let num = \"\";\r\n while (!isNaN(smiles[index])) {\r\n num += smiles[index];\r\n index++;\r\n if (index >= smiles.length) {\r\n break;\r\n }\r\n }\r\n index--;\r\n numbers.add(num);\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * return index of first occurrence number\r\n * @param smiles\r\n * @param number\r\n * @return {number}\r\n */\r\n static findFirst(smiles, number) {\r\n return smiles.indexOf(number);\r\n }\r\n\r\n /**\r\n * return index of first occurrence number from index + 1\r\n * @param smiles\r\n * @param from range no including this point (from, Infinity) = [from + 1, Infinity)\r\n * @param number\r\n * @return {*}\r\n */\r\n static findSecond(smiles, from, number) {\r\n let result = smiles.indexOf(number, from);\r\n if (result === -1) {\r\n throw \"Not Found\";\r\n }\r\n return result;\r\n }\r\n\r\n\r\n smilesNumbersAdd(vertex) {\r\n let numbers = '';\r\n for (let i = 0; i < vertex.digits.length; ++i) {\r\n let num = vertex.digits[i];\r\n if (this._printedDigits.some(e => e === num)) {\r\n let nextVertex = this.vertices.find(e => e.digits.includes(num) && e.id !== vertex.id);\r\n let intersection = vertex.edges.filter(element => nextVertex.edges.includes(element));\r\n\r\n if (intersection.length > 0) {\r\n let bond = this.edges[intersection[0]].bondType;\r\n if (bond !== '-') {\r\n numbers += bond;\r\n }\r\n }\r\n }\r\n\r\n this._printedDigits.push(num);\r\n let numString = num.toString();\r\n if (numString.length === 1) {\r\n numbers += numString;\r\n } else {\r\n numbers += '%' + numString;\r\n }\r\n }\r\n return numbers;\r\n }\r\n\r\n /**\r\n * Return other vertex id then the actual vertex id\r\n * when vertexId === sourceId return targetId\r\n * when vertexId === targetId return sourceId\r\n * @param {Number} vertexId actual vertex id\r\n * @param {Number} sourceId source vertex id\r\n * @param {Number} targetId target vertex id\r\n * @return {Number}\r\n */\r\n static getProperVertex(vertexId, sourceId, targetId) {\r\n if (vertexId === sourceId) return targetId;\r\n else return sourceId;\r\n }\r\n\r\n static repairNumbers(smiles) {\r\n try {\r\n let numbers = Array.from(this.getNumbers(smiles));\r\n numbers.sort(function (a, b) {\r\n return b - a\r\n });\r\n\r\n let index = 1;\r\n for (let number of numbers) {\r\n if (index === number) {\r\n continue;\r\n }\r\n let first = this.findFirst(smiles, number);\r\n if (number > 9) {\r\n smiles = smiles.slice(0, first - 1) + index + smiles.slice(first + number.toString().length);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second - 1) + index + smiles.slice(second + number.toString().length);\r\n } else {\r\n smiles = smiles.slice(0, first) + index + smiles.slice(first + 1);\r\n let second = this.findSecond(smiles, first + 1, number);\r\n smiles = smiles.slice(0, second) + index + smiles.slice(second + 1);\r\n }\r\n index++;\r\n }\r\n } catch (e) {\r\n return smiles;\r\n }\r\n return smiles;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from SMILES\r\n * example CCC(CC)(C) -> CCC(CC)C\r\n * example C(=O)C(C(C)) -> C(=O)CCC\r\n * @param {Array} stackRight\r\n * @return {Array}\r\n */\r\n static removeUnnecessaryParentheses(stackRight) {\r\n if (stackRight.length === 0) return [];\r\n let stackLeft = [], lastLiteral = \"\", literal = \"\";\r\n while (stackRight.length > 0) {\r\n literal = stackRight.shift();\r\n if ((\")\".localeCompare(literal) === 0 && \")\".localeCompare(lastLiteral) === 0)) {\r\n Graph.removeParentheses(stackLeft, false, literal);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n lastLiteral = literal;\r\n }\r\n\r\n literal = stackLeft.pop();\r\n if ((\")\".localeCompare(literal) === 0 && stackRight.length === 0)) {\r\n Graph.removeParentheses(stackLeft);\r\n } else {\r\n stackLeft.push(literal);\r\n }\r\n return stackLeft;\r\n }\r\n\r\n /**\r\n * Remove unnecessary parentheses from stack\r\n * go through stack and when find proper closing bracket,\r\n * then remove it and push back removed data when searching in stack\r\n * @param {Array} stack with unnecessary parentheses to remove\r\n * @param {Boolean} end treat with situation when \")\" is last character of stack -> end = true, else where end = false\r\n * @param {String} literal, when end = false, need to pop from stack and at the end add literal back to stack\r\n */\r\n static removeParentheses(stack, end = true, literal = \"\") {\r\n let stackTmp = [];\r\n let leftBraces = 0, rightBraces = 1;\r\n if (!end) {\r\n stack.pop();\r\n }\r\n while (true) {\r\n let lit = stack.pop();\r\n if (\"(\".localeCompare(lit) === 0) {\r\n leftBraces++;\r\n } else if (\")\".localeCompare(lit) === 0) {\r\n rightBraces++;\r\n }\r\n if (leftBraces === rightBraces) {\r\n Graph.moveAllValuesInStackToAnotherStack(stackTmp, stack);\r\n if (!end) {\r\n stack.push(literal);\r\n }\r\n break;\r\n }\r\n stackTmp.push(lit);\r\n }\r\n }\r\n\r\n /**\r\n * Remove all values from stackSource and push it to stackDestination\r\n * @param {Array} stackSource stack to remove values\r\n * @param {Array} stackDestination stack to add values from stackSource\r\n */\r\n static moveAllValuesInStackToAnotherStack(stackSource, stackDestination) {\r\n while (stackSource.length > 0) {\r\n stackDestination.push(stackSource.pop());\r\n }\r\n }\r\n\r\n /**\r\n * Check last value of stack\r\n * if it one of (, -, = or # then remove all characters in stack to first ( from the end of stack\r\n * elsewhere add ) to stack\r\n * @param {Array} stackSmiles\r\n */\r\n static checkStack(stackSmiles) {\r\n switch (stackSmiles[stackSmiles.length - 1]) {\r\n case \"(\":\r\n case \"-\":\r\n case \"=\":\r\n case \"#\":\r\n Graph.removeAllFromStackToFirstLeftBrace(stackSmiles);\r\n break;\r\n default:\r\n stackSmiles.push(\")\");\r\n }\r\n }\r\n\r\n /**\r\n * Remove all characters from stack to first \"(\"\r\n * @param {Array} stackSmiles\r\n */\r\n static removeAllFromStackToFirstLeftBrace(stackSmiles) {\r\n let literal = stackSmiles.pop();\r\n while (literal !== \"(\") {\r\n if (stackSmiles.length === 0) break;\r\n literal = stackSmiles.pop();\r\n }\r\n }\r\n\r\n /**\r\n * Add bond type to stack\r\n * if edge have = or # bond type add it to stack\r\n * @param {Edge} edge\r\n * @param {Array} stackSmiles\r\n */\r\n static addBondTypeToStack(edge, stackSmiles) {\r\n if (edge.bondType === \"=\" || edge.bondType === \"#\") {\r\n stackSmiles.push(edge.bondType);\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Graph;\r\n","//@ts-check\r\nconst Vector2 = require('./Vector2')\r\n\r\n/** \r\n * A class representing a line.\r\n * \r\n * @property {Vector2} from The Vector2 defining the start of the line.\r\n * @property {Vector2} to The Vector2 defining the end of the line.\r\n * @property {String} elementFrom The element symbol associated with the start of the line.\r\n * @property {String} elementTo The element symbol associated with the end of the line.\r\n * @property {Boolean} chiralFrom A boolean indicating whether or not the source atom is a chiral center.\r\n * @property {Boolean} chiralTo A boolean indicating whether or tno the target atom is a chiral center.\r\n */\r\nclass Line {\r\n /**\r\n * The constructor for the class Line.\r\n *\r\n * @param {Vector2} [from=new Vector2(0, 0)] A vector marking the beginning of the line.\r\n * @param {Vector2} [to=new Vector2(0, 0)] A vector marking the end of the line.\r\n * @param {string} [elementFrom=null] A one-letter representation of the element associated with the vector marking the beginning of the line.\r\n * @param {string} [elementTo=null] A one-letter representation of the element associated with the vector marking the end of the line.\r\n * @param {Boolean} [chiralFrom=false] Whether or not the from atom is a chiral center.\r\n * @param {Boolean} [chiralTo=false] Whether or not the to atom is a chiral center.\r\n * @param {Boolean} [isDecayPoint=false] Whether or not the edge is a decay point\r\n */\r\n constructor(from = new Vector2(0,0), to = new Vector2(0, 0), elementFrom = null, elementTo = null, chiralFrom = false, chiralTo = false, isDecayPoint = false) {\r\n this.from = from;\r\n this.to = to;\r\n this.elementFrom = elementFrom;\r\n this.elementTo = elementTo;\r\n this.chiralFrom = chiralFrom;\r\n this.chiralTo = chiralTo;\r\n this.isDecayPoint = isDecayPoint;\r\n }\r\n\r\n /**\r\n * Clones this line and returns the clone.\r\n *\r\n * @returns {Line} A clone of this line.\r\n */\r\n clone() {\r\n return new Line(this.from.clone(), this.to.clone(), this.elementFrom, this.elementTo);\r\n }\r\n\r\n /**\r\n * Returns the length of this line.\r\n *\r\n * @returns {Number} The length of this line.\r\n */\r\n getLength() {\r\n return Math.sqrt(Math.pow(this.to.x - this.from.x, 2) + \r\n Math.pow(this.to.y - this.from.y, 2));\r\n }\r\n\r\n\r\n /**\r\n * Returns the angle of the line in relation to the coordinate system (the x-axis).\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n // Get the angle between the line and the x-axis\r\n let diff = Vector2.subtract(this.getRightVector(), this.getLeftVector());\r\n return diff.angle();\r\n }\r\n\r\n /**\r\n * Returns the right vector (the vector with the larger x value).\r\n *\r\n * @returns {Vector2} The right vector.\r\n */\r\n getRightVector() {\r\n // Return the vector with the larger x value (the right one)\r\n if (this.from.x < this.to.x) {\r\n return this.to;\r\n } else {\r\n return this.from;\r\n }\r\n }\r\n \r\n /**\r\n * Returns the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {Vector2} The left vector.\r\n */\r\n getLeftVector() {\r\n // Return the vector with the smaller x value (the left one)\r\n if (this.from.x < this.to.x) {\r\n return this.from;\r\n } else {\r\n return this.to;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the right vector (the vector with the larger x value).\r\n *\r\n * @returns {String} The element associated with the right vector.\r\n */\r\n getRightElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementTo;\r\n } else {\r\n return this.elementFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the element associated with the left vector (the vector with the smaller x value).\r\n *\r\n * @returns {String} The element associated with the left vector.\r\n */\r\n getLeftElement() {\r\n if (this.from.x < this.to.x) {\r\n return this.elementFrom;\r\n } else {\r\n return this.elementTo;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the right vector (the vector with the larger x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the right vector is a chiral center.\r\n */\r\n getRightChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralTo;\r\n } else {\r\n return this.chiralFrom;\r\n }\r\n }\r\n\r\n /**\r\n * Returns whether or not the atom associated with the left vector (the vector with the smaller x value) is a chiral center.\r\n *\r\n * @returns {Boolean} Whether or not the atom associated with the left vector is a chiral center.\r\n */\r\n getLeftChiral() {\r\n if (this.from.x < this.to.x) {\r\n return this.chiralFrom;\r\n } else {\r\n return this.chiralTo;\r\n }\r\n }\r\n\r\n /**\r\n * Set the value of the right vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setRightVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.to.x = x;\r\n this.to.y = y;\r\n } else {\r\n this.from.x = x;\r\n this.from.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Set the value of the left vector.\r\n *\r\n * @param {Number} x The x value.\r\n * @param {Number} y The y value.\r\n * @returns {Line} This line.\r\n */\r\n setLeftVector(x, y) {\r\n if (this.from.x < this.to.x) {\r\n this.from.x = x;\r\n this.from.y = y;\r\n } else {\r\n this.to.x = x;\r\n this.to.y = y;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this line to be aligned with the x-axis. The center of rotation is the left vector.\r\n *\r\n * @returns {Line} This line.\r\n */\r\n rotateToXAxis() {\r\n let left = this.getLeftVector();\r\n \r\n this.setRightVector(left.x + this.getLength(), left.y);\r\n \r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate the line by a given value (in radians). The center of rotation is the left vector.\r\n *\r\n * @param {Number} theta The angle (in radians) to rotate the line.\r\n * @returns {Line} This line.\r\n */\r\n rotate(theta) {\r\n let l = this.getLeftVector();\r\n let r = this.getRightVector();\r\n let sinTheta = Math.sin(theta);\r\n let cosTheta = Math.cos(theta);\r\n\r\n let x = cosTheta * (r.x - l.x) - sinTheta * (r.y - l.y) + l.x;\r\n let y = sinTheta * (r.x - l.x) - cosTheta * (r.y - l.y) + l.y;\r\n \r\n this.setRightVector(x, y);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"from\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenFrom(by) {\r\n let f = Vector2.subtract(this.to, this.from);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.from.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from the \"to\" direction by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shortenTo(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by);\r\n \r\n this.to.add(f);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shorten the right side.\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenRight(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenTo(by);\r\n } else {\r\n this.shortenFrom(by);\r\n }\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Shorten the left side.\r\n * \r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} Returns itself.\r\n */\r\n shortenLeft(by) {\r\n if (this.from.x < this.to.x) {\r\n this.shortenFrom(by);\r\n } else {\r\n this.shortenTo(by);\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Shortens this line from both directions by a given value (in pixels).\r\n *\r\n * @param {Number} by The length in pixels to shorten the vector by.\r\n * @returns {Line} This line.\r\n */\r\n shorten(by) {\r\n let f = Vector2.subtract(this.from, this.to);\r\n \r\n f.normalize();\r\n f.multiplyScalar(by / 2.0);\r\n \r\n this.to.add(f);\r\n this.from.subtract(f);\r\n\r\n return this;\r\n }\r\n}\r\n\r\nmodule.exports = Line;","/** \r\n * A static class containing helper functions for math-related tasks. \r\n */\r\nclass MathHelper {\r\n /**\r\n * Rounds a value to a given number of decimals.\r\n *\r\n * @static\r\n * @param {Number} value A number.\r\n * @param {Number} decimals The number of decimals.\r\n * @returns {Number} A number rounded to a given number of decimals.\r\n */\r\n static round(value, decimals) {\r\n decimals = decimals ? decimals : 1;\r\n return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);\r\n }\r\n\r\n /**\r\n * Returns the means of the angles contained in an array. In radians.\r\n *\r\n * @static\r\n * @param {Number[]} arr An array containing angles (in radians).\r\n * @returns {Number} The mean angle in radians.\r\n */\r\n static meanAngle(arr) {\r\n let sin = 0.0;\r\n let cos = 0.0;\r\n \r\n for (var i = 0; i < arr.length; i++) {\r\n sin += Math.sin(arr[i]);\r\n cos += Math.cos(arr[i]);\r\n }\r\n\r\n return Math.atan2(sin / arr.length, cos / arr.length);\r\n }\r\n\r\n /**\r\n * Returns the inner angle of a n-sided regular polygon.\r\n *\r\n * @static\r\n * @param {Number} n Number of sides of a regular polygon.\r\n * @returns {Number} The inner angle of a given regular polygon.\r\n */\r\n static innerAngle(n) {\r\n return MathHelper.toRad((n - 2) * 180 / n);\r\n }\r\n\r\n /**\r\n * Returns the circumradius of a n-sided regular polygon with a given side-length.\r\n *\r\n * @static\r\n * @param {Number} s The side length of the regular polygon.\r\n * @param {Number} n The number of sides.\r\n * @returns {Number} The circumradius of the regular polygon.\r\n */\r\n static polyCircumradius(s, n) {\r\n return s / (2 * Math.sin(Math.PI / n));\r\n }\r\n\r\n /**\r\n * Returns the apothem of a regular n-sided polygon based on its radius.\r\n *\r\n * @static\r\n * @param {Number} r The radius.\r\n * @param {Number} n The number of edges of the regular polygon.\r\n * @returns {Number} The apothem of a n-sided polygon based on its radius.\r\n */\r\n static apothem(r, n) {\r\n return r * Math.cos(Math.PI / n);\r\n }\r\n\r\n static apothemFromSideLength(s, n) {\r\n let r = MathHelper.polyCircumradius(s, n);\r\n \r\n return MathHelper.apothem(r, n);\r\n }\r\n\r\n /**\r\n * The central angle of a n-sided regular polygon. In radians.\r\n *\r\n * @static\r\n * @param {Number} n The number of sides of the regular polygon.\r\n * @returns {Number} The central angle of the n-sided polygon in radians.\r\n */\r\n static centralAngle(n) {\r\n return MathHelper.toRad(360 / n);\r\n }\r\n\r\n /**\r\n * Convertes radians to degrees.\r\n *\r\n * @static\r\n * @param {Number} rad An angle in radians.\r\n * @returns {Number} The angle in degrees.\r\n */\r\n static toDeg(rad) {\r\n return rad * MathHelper.degFactor;\r\n }\r\n\r\n /**\r\n * Converts degrees to radians.\r\n *\r\n * @static\r\n * @param {Number} deg An angle in degrees.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static toRad(deg) {\r\n return deg * MathHelper.radFactor;\r\n }\r\n\r\n /**\r\n * Returns the parity of the permutation (1 or -1)\r\n * @param {(Array|Uint8Array)} arr An array containing the permutation.\r\n * @returns {Number} The parity of the permutation (1 or -1), where 1 means even and -1 means odd.\r\n */\r\n static parityOfPermutation(arr) {\r\n let visited = new Uint8Array(arr.length);\r\n let evenLengthCycleCount = 0;\r\n\r\n let traverseCycle = function(i, cycleLength = 0) {\r\n if (visited[i] === 1) {\r\n return cycleLength;\r\n }\r\n\r\n cycleLength++;\r\n\r\n visited[i] = 1;\r\n return traverseCycle(arr[i], cycleLength);\r\n }\r\n\r\n for (var i = 0; i < arr.length; i++) {\r\n if (visited[i] === 1) {\r\n continue;\r\n }\r\n\r\n let cycleLength = traverseCycle(i);\r\n evenLengthCycleCount += (1 - cycleLength % 2);\r\n }\r\n\r\n return evenLengthCycleCount % 2 ? -1 : 1;\r\n }\r\n\r\n /** The factor to convert degrees to radians. */\r\n static get radFactor() {\r\n return Math.PI / 180.0;\r\n }\r\n\r\n /** The factor to convert radians to degrees. */\r\n static get degFactor() {\r\n return 180.0 / Math.PI;\r\n }\r\n\r\n /** Two times PI. */\r\n static get twoPI() {\r\n return 2.0 * Math.PI;\r\n }\r\n}\r\n\r\nmodule.exports = MathHelper;","/**\r\n *@property {boolean} value is boolean\r\n */\r\nclass MutableBoolean {\r\n\r\n /**\r\n * @param {boolean} value\r\n */\r\n constructor(value) {\r\n this.value = value;\r\n }\r\n\r\n setValue(value) {\r\n this.value = value;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableBoolean;\r\n","/**\r\n * @param {Number} value\r\n */\r\nclass MutableCounter {\r\n\r\n constructor() {\r\n this.value = 0;\r\n }\r\n\r\n increment() {\r\n this.value++;\r\n }\r\n\r\n reset() {\r\n this.value = 0;\r\n }\r\n\r\n getValue() {\r\n return this.value;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = MutableCounter;\r\n","\r\nclass Neighbour {\r\n\r\n constructor(neighbour, direction) {\r\n this.neighbour = neighbour;\r\n this.direction = direction;\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Neighbour;\r\n","//@ts-check\r\nconst VertexState = require(\"./VertexState\");\r\n\r\nclass Node {\r\n\r\n constructor(id) {\r\n this.id = id;\r\n this.neighbours = [];\r\n this.onRing = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n }\r\n\r\n addNeighbour(neighbour) {\r\n this.neighbours.push(neighbour);\r\n }\r\n\r\n}\r\n\r\nmodule.exports = Node;\r\n","// WHEN REPLACING, CHECK FOR:\r\n// KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\nmodule.exports = (function () {\r\n \"use strict\";\r\n\r\n /*\r\n * Generated by PEG.js 0.10.0.\r\n *\r\n * http://pegjs.org/\r\n */\r\n\r\n function peg$subclass(child, parent) {\r\n function ctor() {\r\n this.constructor = child;\r\n }\r\n ctor.prototype = parent.prototype;\r\n child.prototype = new ctor();\r\n }\r\n\r\n function peg$SyntaxError(message, expected, found, location) {\r\n this.message = message;\r\n this.expected = expected;\r\n this.found = found;\r\n this.location = location;\r\n this.name = \"SyntaxError\";\r\n\r\n if (typeof Error.captureStackTrace === \"function\") {\r\n Error.captureStackTrace(this, peg$SyntaxError);\r\n }\r\n }\r\n\r\n peg$subclass(peg$SyntaxError, Error);\r\n\r\n peg$SyntaxError.buildMessage = function (expected, found) {\r\n var DESCRIBE_EXPECTATION_FNS = {\r\n literal: function (expectation) {\r\n return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";\r\n },\r\n\r\n \"class\": function (expectation) {\r\n var escapedParts = \"\",\r\n i;\r\n\r\n for (i = 0; i < expectation.parts.length; i++) {\r\n escapedParts += expectation.parts[i] instanceof Array ?\r\n classEscape(expectation.parts[i][0]) + \"-\" + classEscape(expectation.parts[i][1]) :\r\n classEscape(expectation.parts[i]);\r\n }\r\n\r\n return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";\r\n },\r\n\r\n any: function (expectation) {\r\n return \"any character\";\r\n },\r\n\r\n end: function (expectation) {\r\n return \"end of input\";\r\n },\r\n\r\n other: function (expectation) {\r\n return expectation.description;\r\n }\r\n };\r\n\r\n function hex(ch) {\r\n return ch.charCodeAt(0).toString(16).toUpperCase();\r\n }\r\n\r\n function literalEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\"/g, '\\\\\"')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function classEscape(s) {\r\n return s\r\n .replace(/\\\\/g, '\\\\\\\\')\r\n .replace(/\\]/g, '\\\\]')\r\n .replace(/\\^/g, '\\\\^')\r\n .replace(/-/g, '\\\\-')\r\n .replace(/\\0/g, '\\\\0')\r\n .replace(/\\t/g, '\\\\t')\r\n .replace(/\\n/g, '\\\\n')\r\n .replace(/\\r/g, '\\\\r')\r\n .replace(/[\\x00-\\x0F]/g, function (ch) {\r\n return '\\\\x0' + hex(ch);\r\n })\r\n .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function (ch) {\r\n return '\\\\x' + hex(ch);\r\n });\r\n }\r\n\r\n function describeExpectation(expectation) {\r\n return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);\r\n }\r\n\r\n function describeExpected(expected) {\r\n var descriptions = new Array(expected.length),\r\n i, j;\r\n\r\n for (i = 0; i < expected.length; i++) {\r\n descriptions[i] = describeExpectation(expected[i]);\r\n }\r\n\r\n descriptions.sort();\r\n\r\n if (descriptions.length > 0) {\r\n for (i = 1, j = 1; i < descriptions.length; i++) {\r\n if (descriptions[i - 1] !== descriptions[i]) {\r\n descriptions[j] = descriptions[i];\r\n j++;\r\n }\r\n }\r\n descriptions.length = j;\r\n }\r\n\r\n switch (descriptions.length) {\r\n case 1:\r\n return descriptions[0];\r\n\r\n case 2:\r\n return descriptions[0] + \" or \" + descriptions[1];\r\n\r\n default:\r\n return descriptions.slice(0, -1).join(\", \") +\r\n \", or \" +\r\n descriptions[descriptions.length - 1];\r\n }\r\n }\r\n\r\n function describeFound(found) {\r\n return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";\r\n }\r\n\r\n return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";\r\n };\r\n\r\n function peg$parse(input, options) {\r\n options = options !== void 0 ? options : {};\r\n\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n var nOpenParentheses = input.split('(').length - 1;\r\n var nCloseParentheses = input.split(')').length - 1;\r\n\r\n if (nOpenParentheses !== nCloseParentheses) {\r\n throw peg$buildSimpleError('The number of opening parentheses does not match the number of closing parentheses.', 0);\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n var peg$FAILED = {},\r\n\r\n peg$startRuleFunctions = {\r\n chain: peg$parsechain\r\n },\r\n peg$startRuleFunction = peg$parsechain,\r\n\r\n peg$c0 = function (s) {\r\n var branches = [];\r\n var rings = [];\r\n\r\n for (var i = 0; i < s[1].length; i++) {\r\n branches.push(s[1][i]);\r\n }\r\n\r\n\r\n for (var i = 0; i < s[2].length; i++) {\r\n var bond = (s[2][i][0]) ? s[2][i][0] : '-';\r\n rings.push({\r\n 'bond': bond,\r\n 'id': s[2][i][1]\r\n });\r\n }\r\n\r\n for (var i = 0; i < s[3].length; i++) {\r\n branches.push(s[3][i]);\r\n }\r\n\r\n for (var i = 0; i < s[6].length; i++) {\r\n branches.push(s[6][i]);\r\n }\r\n\r\n return {\r\n 'atom': s[0],\r\n 'isBracket': s[0].element ? true : false,\r\n 'branches': branches,\r\n 'branchCount': branches.length,\r\n 'ringbonds': rings,\r\n 'ringbondCount': rings.length,\r\n 'bond': s[4] ? s[4] : '-',\r\n 'next': s[5],\r\n 'hasNext': s[5] ? true : false\r\n }\r\n\r\n return s;\r\n },\r\n peg$c1 = \"(\",\r\n peg$c2 = peg$literalExpectation(\"(\", false),\r\n peg$c3 = \")\",\r\n peg$c4 = peg$literalExpectation(\")\", false),\r\n peg$c5 = function (b) {\r\n var bond = (b[1]) ? b[1] : '-';\r\n b[2].branchBond = bond;\r\n return b[2]\r\n },\r\n peg$c6 = function (a) {\r\n return a;\r\n },\r\n peg$c7 = /^[\\-=#$:\\/\\\\.]/,\r\n peg$c8 = peg$classExpectation([\"-\", \"=\", \"#\", \"$\", \":\", \"/\", \"\\\\\", \".\"], false, false),\r\n peg$c9 = function (b) {\r\n return b;\r\n },\r\n peg$c10 = \"[\",\r\n peg$c11 = peg$literalExpectation(\"[\", false),\r\n peg$c12 = \"se\",\r\n peg$c13 = peg$literalExpectation(\"se\", false),\r\n peg$c14 = \"as\",\r\n peg$c15 = peg$literalExpectation(\"as\", false),\r\n peg$c16 = \"]\",\r\n peg$c17 = peg$literalExpectation(\"]\", false),\r\n peg$c18 = function (b) {\r\n return {\r\n 'isotope': b[1],\r\n 'element': b[2],\r\n 'chirality': b[3],\r\n 'hcount': b[4],\r\n 'charge': b[5],\r\n 'class': b[6]\r\n }\r\n },\r\n peg$c19 = \"B\",\r\n peg$c20 = peg$literalExpectation(\"B\", false),\r\n peg$c21 = \"r\",\r\n peg$c22 = peg$literalExpectation(\"r\", false),\r\n peg$c23 = \"C\",\r\n peg$c24 = peg$literalExpectation(\"C\", false),\r\n peg$c25 = \"l\",\r\n peg$c26 = peg$literalExpectation(\"l\", false),\r\n peg$c27 = /^[NOPSFI]/,\r\n peg$c28 = peg$classExpectation([\"N\", \"O\", \"P\", \"S\", \"F\", \"I\"], false, false),\r\n peg$c29 = function (o) {\r\n if (o.length > 1) return o.join('');\r\n return o;\r\n },\r\n peg$c30 = /^[bcnops]/,\r\n peg$c31 = peg$classExpectation([\"b\", \"c\", \"n\", \"o\", \"p\", \"s\"], false, false),\r\n peg$c32 = \"*\",\r\n peg$c33 = peg$literalExpectation(\"*\", false),\r\n peg$c34 = function (w) {\r\n return w;\r\n },\r\n peg$c35 = /^[A-Z]/,\r\n peg$c36 = peg$classExpectation([\r\n [\"A\", \"Z\"]\r\n ], false, false),\r\n peg$c37 = /^[a-z]/,\r\n peg$c38 = peg$classExpectation([\r\n [\"a\", \"z\"]\r\n ], false, false),\r\n peg$c39 = function (e) {\r\n return e.join('');\r\n },\r\n peg$c40 = \"%\",\r\n peg$c41 = peg$literalExpectation(\"%\", false),\r\n peg$c42 = /^[1-9]/,\r\n peg$c43 = peg$classExpectation([\r\n [\"1\", \"9\"]\r\n ], false, false),\r\n peg$c44 = /^[0-9]/,\r\n peg$c45 = peg$classExpectation([\r\n [\"0\", \"9\"]\r\n ], false, false),\r\n peg$c46 = function (r) {\r\n if (r.length == 1) return Number(r);\r\n return Number(r.join('').replace('%', ''));\r\n },\r\n peg$c47 = \"@\",\r\n peg$c48 = peg$literalExpectation(\"@\", false),\r\n peg$c49 = \"TH\",\r\n peg$c50 = peg$literalExpectation(\"TH\", false),\r\n peg$c51 = /^[12]/,\r\n peg$c52 = peg$classExpectation([\"1\", \"2\"], false, false),\r\n peg$c53 = \"AL\",\r\n peg$c54 = peg$literalExpectation(\"AL\", false),\r\n peg$c55 = \"SP\",\r\n peg$c56 = peg$literalExpectation(\"SP\", false),\r\n peg$c57 = /^[1-3]/,\r\n peg$c58 = peg$classExpectation([\r\n [\"1\", \"3\"]\r\n ], false, false),\r\n peg$c59 = \"TB\",\r\n peg$c60 = peg$literalExpectation(\"TB\", false),\r\n peg$c61 = \"OH\",\r\n peg$c62 = peg$literalExpectation(\"OH\", false),\r\n peg$c63 = function (c) {\r\n if (!c[1]) return '@';\r\n if (c[1] == '@') return '@@';\r\n\r\n return c[1].join('').replace(',', '');\r\n },\r\n peg$c64 = function (c) {\r\n return c;\r\n },\r\n peg$c65 = \"+\",\r\n peg$c66 = peg$literalExpectation(\"+\", false),\r\n peg$c67 = function (c) {\r\n if (!c[1]) return 1;\r\n if (c[1] != '+') return Number(c[1].join(''));\r\n return 2;\r\n },\r\n peg$c68 = \"-\",\r\n peg$c69 = peg$literalExpectation(\"-\", false),\r\n peg$c70 = function (c) {\r\n if (!c[1]) return -1;\r\n if (c[1] != '-') return -Number(c[1].join(''));\r\n return -2;\r\n },\r\n peg$c71 = \"H\",\r\n peg$c72 = peg$literalExpectation(\"H\", false),\r\n peg$c73 = function (h) {\r\n if (h[1]) return Number(h[1]);\r\n return 1;\r\n },\r\n peg$c74 = \":\",\r\n peg$c75 = peg$literalExpectation(\":\", false),\r\n peg$c76 = /^[0]/,\r\n peg$c77 = peg$classExpectation([\"0\"], false, false),\r\n peg$c78 = function (c) {\r\n return Number(c[1][0] + c[1][1].join(''));\r\n },\r\n peg$c79 = function (i) {\r\n return Number(i.join(''));\r\n },\r\n\r\n peg$currPos = 0,\r\n peg$savedPos = 0,\r\n peg$posDetailsCache = [{\r\n line: 1,\r\n column: 1\r\n }],\r\n peg$maxFailPos = 0,\r\n peg$maxFailExpected = [],\r\n peg$silentFails = 0,\r\n\r\n peg$result;\r\n\r\n if (\"startRule\" in options) {\r\n if (!(options.startRule in peg$startRuleFunctions)) {\r\n throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");\r\n }\r\n\r\n peg$startRuleFunction = peg$startRuleFunctions[options.startRule];\r\n }\r\n\r\n function text() {\r\n return input.substring(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function location() {\r\n return peg$computeLocation(peg$savedPos, peg$currPos);\r\n }\r\n\r\n function expected(description, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildStructuredError(\r\n [peg$otherExpectation(description)],\r\n input.substring(peg$savedPos, peg$currPos),\r\n location\r\n );\r\n }\r\n\r\n function error(message, location) {\r\n location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos)\r\n\r\n throw peg$buildSimpleError(message, location);\r\n }\r\n\r\n function peg$literalExpectation(text, ignoreCase) {\r\n return {\r\n type: \"literal\",\r\n text: text,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$classExpectation(parts, inverted, ignoreCase) {\r\n return {\r\n type: \"class\",\r\n parts: parts,\r\n inverted: inverted,\r\n ignoreCase: ignoreCase\r\n };\r\n }\r\n\r\n function peg$anyExpectation() {\r\n return {\r\n type: \"any\"\r\n };\r\n }\r\n\r\n function peg$endExpectation() {\r\n return {\r\n type: \"end\"\r\n };\r\n }\r\n\r\n function peg$otherExpectation(description) {\r\n return {\r\n type: \"other\",\r\n description: description\r\n };\r\n }\r\n\r\n function peg$computePosDetails(pos) {\r\n var details = peg$posDetailsCache[pos],\r\n p;\r\n\r\n if (details) {\r\n return details;\r\n } else {\r\n p = pos - 1;\r\n while (!peg$posDetailsCache[p]) {\r\n p--;\r\n }\r\n\r\n details = peg$posDetailsCache[p];\r\n details = {\r\n line: details.line,\r\n column: details.column\r\n };\r\n\r\n while (p < pos) {\r\n if (input.charCodeAt(p) === 10) {\r\n details.line++;\r\n details.column = 1;\r\n } else {\r\n details.column++;\r\n }\r\n\r\n p++;\r\n }\r\n\r\n peg$posDetailsCache[pos] = details;\r\n return details;\r\n }\r\n }\r\n\r\n function peg$computeLocation(startPos, endPos) {\r\n var startPosDetails = peg$computePosDetails(startPos),\r\n endPosDetails = peg$computePosDetails(endPos);\r\n\r\n return {\r\n start: {\r\n offset: startPos,\r\n line: startPosDetails.line,\r\n column: startPosDetails.column\r\n },\r\n end: {\r\n offset: endPos,\r\n line: endPosDetails.line,\r\n column: endPosDetails.column\r\n }\r\n };\r\n }\r\n\r\n function peg$fail(expected) {\r\n if (peg$currPos < peg$maxFailPos) {\r\n return;\r\n }\r\n\r\n if (peg$currPos > peg$maxFailPos) {\r\n peg$maxFailPos = peg$currPos;\r\n peg$maxFailExpected = [];\r\n }\r\n\r\n peg$maxFailExpected.push(expected);\r\n }\r\n\r\n function peg$buildSimpleError(message, location) {\r\n return new peg$SyntaxError(message, null, null, location);\r\n }\r\n\r\n function peg$buildStructuredError(expected, found, location) {\r\n return new peg$SyntaxError(\r\n peg$SyntaxError.buildMessage(expected, found),\r\n expected,\r\n found,\r\n location\r\n );\r\n }\r\n\r\n function peg$parsechain() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n s2 = peg$parseatom();\r\n if (s2 !== peg$FAILED) {\r\n s3 = [];\r\n s4 = peg$parsebranch();\r\n while (s4 !== peg$FAILED) {\r\n s3.push(s4);\r\n s4 = peg$parsebranch();\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = [];\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n while (s5 !== peg$FAILED) {\r\n s4.push(s5);\r\n s5 = peg$currPos;\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsering();\r\n if (s7 !== peg$FAILED) {\r\n s6 = [s6, s7];\r\n s5 = s6;\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s5;\r\n s5 = peg$FAILED;\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n s6 = peg$parsebranch();\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n s6 = peg$parsebranch();\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsebond();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsechain();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = [];\r\n s9 = peg$parsebranch();\r\n while (s9 !== peg$FAILED) {\r\n s8.push(s9);\r\n s9 = peg$parsebranch();\r\n }\r\n if (s8 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c0(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebranch() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 40) {\r\n s2 = peg$c1;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c2);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parsebond();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s4 = peg$parsechain();\r\n if (s4 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 41) {\r\n s5 = peg$c3;\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c4);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c5(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseatom() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseorganicsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsearomaticsymbol();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsebracketatom();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebond() {\r\n var s0, s1;\r\n s0 = peg$currPos;\r\n if (peg$c7.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n\r\n // Hack to resolve problem caused by:\r\n // O=C(N[C@@H](CC(O)=O)C(N[C@H](C1=CC=C(O)C=C1)C(N[C@@H](CC(O)=O)C(NCC(N[C@@H](C(N[C@@H]([C@H](C)CC(O)=O)C(N/C(C(O[C@H](C)[C@@H]2NC([C@H](CO)NC(C(O3)C3CCC)=O)=O)=O)=C\\\\\\\\C4=CNC5=C4C=CC=C5)=O)=O)[C@H](O)C(N)=O)=O)=O)=O)=O)[C@H](CC(O)=O)NC([C@@H](CC6=CNC7=C6C=CC=C7)NC2=O)=O\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n if (s1 === input.charAt(peg$currPos + 1)) {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n throw peg$buildSimpleError('The parser encountered a bond repetition.', peg$currPos + 1);\r\n }\r\n }\r\n // KEEP THIS WHEN REGENERATING THE PARSER !!\r\n\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c8);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c9(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsebracketatom() {\r\n var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 91) {\r\n s2 = peg$c10;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c11);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$parseisotope();\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c12) {\r\n s4 = peg$c12;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c13);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n if (input.substr(peg$currPos, 2) === peg$c14) {\r\n s4 = peg$c14;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c15);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsearomaticsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parseelementsymbol();\r\n if (s4 === peg$FAILED) {\r\n s4 = peg$parsewildcard();\r\n }\r\n }\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = peg$parsechiral();\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s6 = peg$parsehcount();\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s7 = peg$parsecharge();\r\n if (s7 === peg$FAILED) {\r\n s7 = null;\r\n }\r\n if (s7 !== peg$FAILED) {\r\n s8 = peg$parseclass();\r\n if (s8 === peg$FAILED) {\r\n s8 = null;\r\n }\r\n if (s8 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 93) {\r\n s9 = peg$c16;\r\n peg$currPos++;\r\n } else {\r\n s9 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c17);\r\n }\r\n }\r\n if (s9 !== peg$FAILED) {\r\n s2 = [s2, s3, s4, s5, s6, s7, s8, s9];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c18(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseorganicsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 66) {\r\n s2 = peg$c19;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c20);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 114) {\r\n s3 = peg$c21;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c22);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 67) {\r\n s2 = peg$c23;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c24);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 108) {\r\n s3 = peg$c25;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c26);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c27.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c28);\r\n }\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c29(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsearomaticsymbol() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (peg$c30.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c31);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c6(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsewildcard() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 42) {\r\n s1 = peg$c32;\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c33);\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c34(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseelementsymbol() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c35.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c36);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c37.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c38);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c39(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsering() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 37) {\r\n s2 = peg$c40;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c41);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 === peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s1 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s1 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c46(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsechiral() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s2 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 64) {\r\n s3 = peg$c47;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c48);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c49) {\r\n s4 = peg$c49;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c50);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c53) {\r\n s4 = peg$c53;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c54);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c51.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c52);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c55) {\r\n s4 = peg$c55;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c56);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c57.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c58);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c59) {\r\n s4 = peg$c59;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c60);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (input.substr(peg$currPos, 2) === peg$c61) {\r\n s4 = peg$c61;\r\n peg$currPos += 2;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c62);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s6 === peg$FAILED) {\r\n s6 = null;\r\n }\r\n if (s6 !== peg$FAILED) {\r\n s4 = [s4, s5, s6];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c63(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsecharge() {\r\n var s0, s1;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$parseposcharge();\r\n if (s1 === peg$FAILED) {\r\n s1 = peg$parsenegcharge();\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c64(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseposcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s2 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 43) {\r\n s3 = peg$c65;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c66);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c67(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsenegcharge() {\r\n var s0, s1, s2, s3, s4, s5;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s2 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (input.charCodeAt(peg$currPos) === 45) {\r\n s3 = peg$c68;\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c69);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s5 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s5 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s5 === peg$FAILED) {\r\n s5 = null;\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c70(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parsehcount() {\r\n var s0, s1, s2, s3;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 72) {\r\n s2 = peg$c71;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c72);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c73(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseclass() {\r\n var s0, s1, s2, s3, s4, s5, s6;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (input.charCodeAt(peg$currPos) === 58) {\r\n s2 = peg$c74;\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c75);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n s3 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s5 = [];\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n while (s6 !== peg$FAILED) {\r\n s5.push(s6);\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s6 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s6 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n }\r\n if (s5 !== peg$FAILED) {\r\n s4 = [s4, s5];\r\n s3 = s4;\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s3;\r\n s3 = peg$FAILED;\r\n }\r\n if (s3 === peg$FAILED) {\r\n if (peg$c76.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c77);\r\n }\r\n }\r\n }\r\n if (s3 !== peg$FAILED) {\r\n s2 = [s2, s3];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c78(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n function peg$parseisotope() {\r\n var s0, s1, s2, s3, s4;\r\n\r\n s0 = peg$currPos;\r\n s1 = peg$currPos;\r\n if (peg$c42.test(input.charAt(peg$currPos))) {\r\n s2 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s2 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c43);\r\n }\r\n }\r\n if (s2 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s3 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s3 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s3 === peg$FAILED) {\r\n s3 = null;\r\n }\r\n if (s3 !== peg$FAILED) {\r\n if (peg$c44.test(input.charAt(peg$currPos))) {\r\n s4 = input.charAt(peg$currPos);\r\n peg$currPos++;\r\n } else {\r\n s4 = peg$FAILED;\r\n if (peg$silentFails === 0) {\r\n peg$fail(peg$c45);\r\n }\r\n }\r\n if (s4 === peg$FAILED) {\r\n s4 = null;\r\n }\r\n if (s4 !== peg$FAILED) {\r\n s2 = [s2, s3, s4];\r\n s1 = s2;\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n } else {\r\n peg$currPos = s1;\r\n s1 = peg$FAILED;\r\n }\r\n if (s1 !== peg$FAILED) {\r\n peg$savedPos = s0;\r\n s1 = peg$c79(s1);\r\n }\r\n s0 = s1;\r\n\r\n return s0;\r\n }\r\n\r\n peg$result = peg$startRuleFunction();\r\n\r\n if (peg$result !== peg$FAILED && peg$currPos === input.length) {\r\n return peg$result;\r\n } else {\r\n if (peg$result !== peg$FAILED && peg$currPos < input.length) {\r\n peg$fail(peg$endExpectation());\r\n }\r\n\r\n throw peg$buildStructuredError(\r\n peg$maxFailExpected,\r\n peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,\r\n peg$maxFailPos < input.length ?\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) :\r\n peg$computeLocation(peg$maxFailPos, peg$maxFailPos)\r\n );\r\n }\r\n }\r\n\r\n return {\r\n SyntaxError: peg$SyntaxError,\r\n parse: peg$parse\r\n };\r\n})();","//@ts-check\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Vertex = require('./Vertex')\r\nconst RingConnection = require('./RingConnection')\r\n\r\n/** \r\n * A class representing a ring.\r\n * \r\n * @property {Number} id The id of this ring.\r\n * @property {Number[]} members An array containing the vertex ids of the ring members.\r\n * @property {Number[]} edges An array containing the edge ids of the edges between the ring members.\r\n * @property {Number[]} insiders An array containing the vertex ids of the vertices contained within the ring if it is a bridged ring.\r\n * @property {Number[]} neighbours An array containing the ids of neighbouring rings.\r\n * @property {Boolean} positioned A boolean indicating whether or not this ring has been positioned.\r\n * @property {Vector2} center The center of this ring.\r\n * @property {Ring[]} rings The rings contained within this ring if this ring is bridged.\r\n * @property {Boolean} isBridged A boolean whether or not this ring is bridged.\r\n * @property {Boolean} isPartOfBridged A boolean whether or not this ring is part of a bridge ring.\r\n * @property {Boolean} isSpiro A boolean whether or not this ring is part of a spiro.\r\n * @property {Boolean} isFused A boolean whether or not this ring is part of a fused ring.\r\n * @property {Number} centralAngle The central angle of this ring.\r\n * @property {Boolean} canFlip A boolean indicating whether or not this ring allows flipping of attached vertices to the inside of the ring.\r\n */\r\nclass Ring {\r\n /**\r\n * The constructor for the class Ring.\r\n *\r\n * @param {Number[]} members An array containing the vertex ids of the members of the ring to be created.\r\n */\r\n constructor(members) {\r\n this.id = null;\r\n this.members = members;\r\n this.edges = [];\r\n this.insiders = [];\r\n this.neighbours = [];\r\n this.positioned = false;\r\n this.center = new Vector2(0, 0);\r\n this.rings = [];\r\n this.isBridged = false;\r\n this.isPartOfBridged = false;\r\n this.isSpiro = false;\r\n this.isFused = false;\r\n this.centralAngle = 0.0;\r\n this.canFlip = true;\r\n }\r\n \r\n /**\r\n * Clones this ring and returns the clone.\r\n *\r\n * @returns {Ring} A clone of this ring.\r\n */\r\n clone() {\r\n let clone = new Ring(this.members);\r\n\r\n clone.id = this.id;\r\n clone.insiders = ArrayHelper.clone(this.insiders);\r\n clone.neighbours = ArrayHelper.clone(this.neighbours);\r\n clone.positioned = this.positioned;\r\n clone.center = this.center.clone();\r\n clone.rings = ArrayHelper.clone(this.rings);\r\n clone.isBridged = this.isBridged;\r\n clone.isPartOfBridged = this.isPartOfBridged;\r\n clone.isSpiro = this.isSpiro;\r\n clone.isFused = this.isFused;\r\n clone.centralAngle = this.centralAngle;\r\n clone.canFlip = this.canFlip;\r\n\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns the size (number of members) of this ring.\r\n *\r\n * @returns {Number} The size (number of members) of this ring.\r\n */\r\n getSize() {\r\n return this.members.length;\r\n }\r\n\r\n /**\r\n * Gets the polygon representation (an array of the ring-members positional vectors) of this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices representing the current molecule.\r\n * @returns {Vector2[]} An array of the positional vectors of the ring members.\r\n */\r\n getPolygon(vertices) {\r\n let polygon = [];\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n polygon.push(vertices[this.members[i]].position);\r\n }\r\n\r\n return polygon;\r\n }\r\n\r\n /**\r\n * Returns the angle of this ring in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n getAngle() {\r\n return Math.PI - this.centralAngle;\r\n }\r\n\r\n /**\r\n * Loops over the members of this ring from a given start position in a direction opposite to the vertex id passed as the previousId.\r\n *\r\n * @param {Vertex[]} vertices The vertices associated with the current molecule.\r\n * @param {Function} callback A callback with the current vertex id as a parameter.\r\n * @param {Number} startVertexId The vertex id of the start vertex.\r\n * @param {Number} previousVertexId The vertex id of the previous vertex (the loop calling the callback function will run in the opposite direction of this vertex).\r\n */\r\n eachMember(vertices, callback, startVertexId, previousVertexId) {\r\n startVertexId = startVertexId || startVertexId === 0 ? startVertexId : this.members[0];\r\n let current = startVertexId;\r\n let max = 0;\r\n\r\n while (current != null && max < 100) {\r\n let prev = current;\r\n \r\n callback(prev);\r\n current = vertices[current].getNextInRing(vertices, this.id, previousVertexId);\r\n previousVertexId = prev;\r\n \r\n // Stop while loop when arriving back at the start vertex\r\n if (current == startVertexId) {\r\n current = null;\r\n }\r\n\r\n max++;\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array containing the neighbouring rings of this ring ordered by ring size.\r\n *\r\n * @param {RingConnection[]} ringConnections An array of ring connections associated with the current molecule.\r\n * @returns {Object[]} An array of neighbouring rings sorted by ring size. Example: { n: 5, neighbour: 1 }.\r\n */\r\n getOrderedNeighbours(ringConnections) {\r\n let orderedNeighbours = Array(this.neighbours.length);\r\n \r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n let vertices = RingConnection.getVertices(ringConnections, this.id, this.neighbours[i]);\r\n \r\n orderedNeighbours[i] = {\r\n n: vertices.length,\r\n neighbour: this.neighbours[i]\r\n };\r\n }\r\n\r\n orderedNeighbours.sort(function (a, b) {\r\n // Sort highest to lowest\r\n return b.n - a.n;\r\n });\r\n\r\n return orderedNeighbours;\r\n }\r\n\r\n /**\r\n * Check whether this ring is an implicitly defined benzene-like (e.g. C1=CC=CC=C1) with 6 members and 3 double bonds.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring is an implicitly defined benzene-like.\r\n */\r\n isBenzeneLike(vertices) {\r\n let db = this.getDoubleBondCount(vertices);\r\n let length = this.members.length;\r\n\r\n return db === 3 && length === 6 ||\r\n db === 2 && length === 5 ;\r\n }\r\n\r\n /**\r\n * Get the number of double bonds inside this ring.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices associated with the current molecule.\r\n * @returns {Number} The number of double bonds inside this ring.\r\n */\r\n getDoubleBondCount(vertices) {\r\n let doubleBondCount = 0;\r\n\r\n for (let i = 0; i < this.members.length; i++) {\r\n let atom = vertices[this.members[i]].value;\r\n\r\n if (atom.bondType === '=' || atom.branchBond === '=') {\r\n doubleBondCount++;\r\n }\r\n }\r\n\r\n return doubleBondCount;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring contains a member with a given vertex id.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n * @returns {Boolean} A boolean indicating whether or not this ring contains a member with the given vertex id.\r\n */\r\n contains(vertexId) {\r\n for (let i = 0; i < this.members.length; i++) {\r\n if (this.members[i] == vertexId) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n\r\nmodule.exports = Ring;","//@ts-check\r\nconst Vertex = require('./Vertex')\r\nconst Ring = require('./Ring')\r\n\r\n/** \r\n * A class representing a ring connection.\r\n * \r\n * @property {Number} id The id of this ring connection.\r\n * @property {Number} firstRingId A ring id.\r\n * @property {Number} secondRingId A ring id.\r\n * @property {Set} vertices A set containing the vertex ids participating in the ring connection.\r\n */\r\nclass RingConnection {\r\n /**\r\n * The constructor for the class RingConnection.\r\n *\r\n * @param {Ring} firstRing A ring.\r\n * @param {Ring} secondRing A ring.\r\n */\r\n constructor(firstRing, secondRing) {\r\n this.id = null;\r\n this.firstRingId = firstRing.id;\r\n this.secondRingId = secondRing.id;\r\n this.vertices = new Set();\r\n\r\n for (var m = 0; m < firstRing.members.length; m++) {\r\n let c = firstRing.members[m];\r\n\r\n for (let n = 0; n < secondRing.members.length; n++) {\r\n let d = secondRing.members[n];\r\n\r\n if (c === d) {\r\n this.addVertex(c);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Adding a vertex to the ring connection.\r\n *\r\n * @param {Number} vertexId A vertex id.\r\n */\r\n addVertex(vertexId) {\r\n this.vertices.add(vertexId);\r\n }\r\n\r\n /**\r\n * Update the ring id of this ring connection that is not the ring id supplied as the second argument.\r\n *\r\n * @param {Number} ringId A ring id. The new ring id to be set.\r\n * @param {Number} otherRingId A ring id. The id that is NOT to be updated.\r\n */\r\n updateOther(ringId, otherRingId) {\r\n if (this.firstRingId === otherRingId) {\r\n this.secondRingId = ringId;\r\n } else {\r\n this.firstRingId = ringId;\r\n }\r\n }\r\n\r\n /**\r\n * Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.\r\n * \r\n * @param {Number} ringId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.\r\n */\r\n containsRing(ringId) {\r\n return this.firstRingId === ringId || this.secondRingId === ringId;\r\n }\r\n\r\n /**\r\n * Checks whether or not this ring connection is a bridge in a bridged ring.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices associated with the current molecule.\r\n * @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.\r\n */\r\n isBridge(vertices) {\r\n if (this.vertices.size > 2) {\r\n return true;\r\n }\r\n\r\n for (let vertexId of this.vertices) {\r\n if(vertices[vertexId].value.rings.length > 2) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two rings are connected by a bridged bond.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.\r\n */\r\n static isBridge(ringConnections, vertices, firstRingId, secondRingId) {\r\n let ringConnection = null;\r\n \r\n for (let i = 0; i < ringConnections.length; i++) {\r\n ringConnection = ringConnections[i];\r\n\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return ringConnection.isBridge(vertices);\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Retruns the neighbouring rings of a given ring.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} ringId A ring id.\r\n * @returns {Number[]} An array of ring ids of neighbouring rings.\r\n */\r\n static getNeighbours(ringConnections, ringId) {\r\n let neighbours = [];\r\n\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n \r\n if (ringConnection.firstRingId === ringId) {\r\n neighbours.push(ringConnection.secondRingId);\r\n } else if (ringConnection.secondRingId === ringId) {\r\n neighbours.push(ringConnection.firstRingId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Returns an array of vertex ids associated with a given ring connection.\r\n *\r\n * @static\r\n * @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.\r\n * @param {Number} firstRingId A ring id.\r\n * @param {Number} secondRingId A ring id.\r\n * @returns {Number[]} An array of vertex ids associated with the ring connection.\r\n */\r\n static getVertices(ringConnections, firstRingId, secondRingId) {\r\n for (let i = 0; i < ringConnections.length; i++) {\r\n let ringConnection = ringConnections[i];\r\n if (ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId ||\r\n ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId) {\r\n return [...ringConnection.vertices];\r\n }\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = RingConnection","//@ts-check\r\nconst Graph = require('./Graph')\r\n\r\n/** A class encapsulating the functionality to find the smallest set of smallest rings in a graph. */\r\nclass SSSR {\r\n /**\r\n * Returns an array containing arrays, each representing a ring from the smallest set of smallest rings in the graph.\r\n * \r\n * @param {Graph} graph A Graph object.\r\n * @param {Boolean} [experimental=false] Whether or not to use experimental SSSR.\r\n * @returns {Array[]} An array containing arrays, each representing a ring from the smallest set of smallest rings in the group.\r\n */\r\n static getRings(graph, experimental=false) {\r\n let adjacencyMatrix = graph.getComponentsAdjacencyMatrix();\r\n if (adjacencyMatrix.length === 0) {\r\n return null;\r\n }\r\n\r\n let connectedComponents = Graph.getConnectedComponents(adjacencyMatrix);\r\n let rings = Array();\r\n\r\n for (var i = 0; i < connectedComponents.length; i++) {\r\n let connectedComponent = connectedComponents[i];\r\n let ccAdjacencyMatrix = graph.getSubgraphAdjacencyMatrix([...connectedComponent]);\r\n\r\n let arrBondCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n let arrRingCount = new Uint16Array(ccAdjacencyMatrix.length);\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n arrRingCount[j] = 0;\r\n arrBondCount[j] = 0;\r\n\r\n for (var k = 0; k < ccAdjacencyMatrix[j].length; k++) {\r\n arrBondCount[j] += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n // Get the edge number and the theoretical number of rings in SSSR\r\n let nEdges = 0;\r\n\r\n for (var j = 0; j < ccAdjacencyMatrix.length; j++) {\r\n for (var k = j + 1; k < ccAdjacencyMatrix.length; k++) {\r\n nEdges += ccAdjacencyMatrix[j][k];\r\n }\r\n }\r\n\r\n let nSssr = nEdges - ccAdjacencyMatrix.length + 1;\r\n\r\n // console.log(nEdges, ccAdjacencyMatrix.length, nSssr);\r\n // console.log(SSSR.getEdgeList(ccAdjacencyMatrix));\r\n // console.log(ccAdjacencyMatrix);\r\n\r\n // If all vertices have 3 incident edges, calculate with different formula (see Euler)\r\n let allThree = true;\r\n for (var j = 0; j < arrBondCount.length; j++) {\r\n if (arrBondCount[j] !== 3) {\r\n allThree = false;\r\n }\r\n }\r\n\r\n if (allThree) {\r\n nSssr = 2.0 + nEdges - ccAdjacencyMatrix.length;\r\n }\r\n\r\n // All vertices are part of one ring if theres only one ring.\r\n if (nSssr === 1) {\r\n rings.push([...connectedComponent]);\r\n continue;\r\n }\r\n \r\n if (experimental) {\r\n nSssr = 999;\r\n }\r\n\r\n let { d, pe, pe_prime } = SSSR.getPathIncludedDistanceMatrices(ccAdjacencyMatrix);\r\n let c = SSSR.getRingCandidates(d, pe, pe_prime);\r\n let sssr = SSSR.getSSSR(c, d, ccAdjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nSssr);\r\n\r\n for (var j = 0; j < sssr.length; j++) {\r\n let ring = Array(sssr[j].size);\r\n let index = 0;\r\n\r\n for (let val of sssr[j]) {\r\n // Get the original id of the vertex back\r\n ring[index++] = connectedComponent[val];\r\n }\r\n\r\n rings.push(ring);\r\n }\r\n }\r\n \r\n\r\n // So, for some reason, this would return three rings for C1CCCC2CC1CCCC2, which is wrong\r\n // As I don't have time to fix this properly, it will stay in. I'm sorry next person who works\r\n // on it. At that point it might be best to reimplement the whole SSSR thing...\r\n return rings;\r\n }\r\n\r\n /**\r\n * Creates a printable string from a matrix (2D array).\r\n * \r\n * @param {Array[]} matrix A 2D array.\r\n * @returns {String} A string representing the matrix.\r\n */\r\n static matrixToString(matrix) {\r\n let str = '';\r\n\r\n for (var i = 0; i < matrix.length; i++) {\r\n for (var j = 0; j < matrix[i].length; j++) {\r\n str += matrix[i][j] + ' ';\r\n }\r\n\r\n str += '\\n';\r\n }\r\n\r\n return str;\r\n }\r\n\r\n /**\r\n * Returnes the two path-included distance matrices used to find the sssr.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Object} The path-included distance matrices. { p1, p2 }\r\n */\r\n static getPathIncludedDistanceMatrices(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let d = Array(length);\r\n let pe = Array(length);\r\n let pe_prime = Array(length);\r\n var l = 0;\r\n var m = 0;\r\n var n = 0;\r\n\r\n var i = length;\r\n while (i--) {\r\n d[i] = Array(length);\r\n pe[i] = Array(length);\r\n pe_prime[i] = Array(length);\r\n\r\n var j = length;\r\n while (j--) {\r\n d[i][j] = (i === j || adjacencyMatrix[i][j] === 1) ? adjacencyMatrix[i][j] : Number.POSITIVE_INFINITY;\r\n\r\n if (d[i][j] === 1) {\r\n pe[i][j] = [[[i, j]]];\r\n } else {\r\n pe[i][j] = Array();\r\n }\r\n\r\n pe_prime[i][j] = Array();\r\n }\r\n }\r\n\r\n var k = length;\r\n var j;\r\n while (k--) {\r\n i = length;\r\n while (i--) {\r\n j = length;\r\n while (j--) {\r\n const previousPathLength = d[i][j];\r\n const newPathLength = d[i][k] + d[k][j];\r\n\r\n if (previousPathLength > newPathLength) {\r\n var l, m, n;\r\n if (previousPathLength === newPathLength + 1) {\r\n pe_prime[i][j] = [pe[i][j].length];\r\n l = pe[i][j].length\r\n while (l--) {\r\n pe_prime[i][j][l] = [pe[i][j][l].length];\r\n m = pe[i][j][l].length\r\n while (m--) {\r\n pe_prime[i][j][l][m] = [pe[i][j][l][m].length];\r\n n = pe[i][j][l][m].length;\r\n while (n--) {\r\n pe_prime[i][j][l][m][n] = [pe[i][j][l][m][0], pe[i][j][l][m][1]];\r\n }\r\n }\r\n }\r\n } else {\r\n pe_prime[i][j] = Array();\r\n }\r\n\r\n d[i][j] = newPathLength;\r\n\r\n pe[i][j] = [[]];\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n pe[i][j][0].push(pe[k][j][0][l]);\r\n }\r\n } else if (previousPathLength === newPathLength) {\r\n if (pe[i][k].length && pe[k][j].length) {\r\n var l;\r\n if (pe[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe[i][j][0] = tmp\r\n }\r\n }\r\n } else if (previousPathLength === newPathLength - 1) {\r\n var l;\r\n if (pe_prime[i][j].length) {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j].push(tmp);\r\n } else {\r\n let tmp = Array();\r\n\r\n l = pe[i][k][0].length;\r\n while (l--) {\r\n tmp.push(pe[i][k][0][l]);\r\n }\r\n\r\n l = pe[k][j][0].length;\r\n while (l--) {\r\n tmp.push(pe[k][j][0][l]);\r\n }\r\n\r\n pe_prime[i][j][0] = tmp;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n d: d,\r\n pe: pe,\r\n pe_prime: pe_prime\r\n };\r\n }\r\n\r\n /**\r\n * Get the ring candidates from the path-included distance matrices.\r\n * \r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @returns {Array[]} The ring candidates.\r\n */\r\n static getRingCandidates(d, pe, pe_prime) {\r\n let length = d.length;\r\n let candidates = Array();\r\n let c = 0;\r\n\r\n for (let i = 0; i < length; i++) {\r\n for (let j = 0; j < length; j++) {\r\n if (d[i][j] === 0 || (pe[i][j].length === 1 && pe_prime[i][j] === 0)) {\r\n continue;\r\n } else {\r\n // c is the number of vertices in the cycle.\r\n if (pe_prime[i][j].length !== 0) {\r\n c = 2 * (d[i][j] + 0.5);\r\n } else {\r\n c = 2 * d[i][j];\r\n }\r\n\r\n if (c !== Infinity) {\r\n candidates.push([c, pe[i][j], pe_prime[i][j]]);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Candidates have to be sorted by c\r\n candidates.sort(function (a, b) {\r\n return a[0] - b[0];\r\n });\r\n\r\n return candidates;\r\n }\r\n\r\n /**\r\n * Searches the candidates for the smallest set of smallest rings.\r\n * \r\n * @param {Array[]} c The candidates.\r\n * @param {Array[]} d The distance matrix.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @param {Array[]} pe A matrix containing the shortest paths.\r\n * @param {Array[]} pe_prime A matrix containing the shortest paths + one vertex.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @param {Number} nsssr The theoretical number of rings in the graph.\r\n * @returns {Set[]} The smallest set of smallest rings.\r\n */\r\n static getSSSR(c, d, adjacencyMatrix, pe, pe_prime, arrBondCount, arrRingCount, nsssr) {\r\n let cSssr = Array();\r\n let allBonds = Array();\r\n\r\n for (let i = 0; i < c.length; i++) {\r\n if (c[i][0] % 2 !== 0) {\r\n for (let j = 0; j < c[i][2].length; j++) {\r\n let bonds = c[i][1][0].concat(c[i][2][j]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n } else {\r\n for (let j = 0; j < c[i][1].length - 1; j++) {\r\n let bonds = c[i][1][j].concat(c[i][1][j + 1]);\r\n // Some bonds are added twice, resulting in [[u, v], [u, v]] instead of [u, v].\r\n // TODO: This is a workaround, fix later. Probably should be a set rather than an array, however the computational overhead\r\n // is probably bigger compared to leaving it like this.\r\n for (var k = 0; k < bonds.length; k++) {\r\n if (bonds[k][0].constructor === Array) bonds[k] = bonds[k][0];\r\n }\r\n\r\n let atoms = SSSR.bondsToAtoms(bonds);\r\n\r\n if (SSSR.getBondCount(atoms, adjacencyMatrix) === atoms.size && !SSSR.pathSetsContain(cSssr, atoms, bonds, allBonds, arrBondCount, arrRingCount)) {\r\n cSssr.push(atoms);\r\n allBonds = allBonds.concat(bonds);\r\n }\r\n\r\n if (cSssr.length > nsssr) {\r\n return cSssr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return cSssr;\r\n }\r\n\r\n /**\r\n * Returns the number of edges in a graph defined by an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of edges in the graph defined by the adjacency matrix.\r\n */\r\n static getEdgeCount(adjacencyMatrix) {\r\n let edgeCount = 0;\r\n let length = adjacencyMatrix.length;\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeCount++;\r\n }\r\n }\r\n }\r\n\r\n return edgeCount;\r\n }\r\n\r\n /**\r\n * Returns an edge list constructed form an adjacency matrix.\r\n * \r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Array[]} An edge list. E.g. [ [ 0, 1 ], ..., [ 16, 2 ] ]\r\n */\r\n static getEdgeList(adjacencyMatrix) {\r\n let length = adjacencyMatrix.length;\r\n let edgeList = Array();\r\n\r\n var i = length - 1;\r\n while (i--) {\r\n var j = length;\r\n while (j--) {\r\n if (adjacencyMatrix[i][j] === 1) {\r\n edgeList.push([i, j]);\r\n }\r\n }\r\n }\r\n\r\n return edgeList;\r\n }\r\n\r\n /**\r\n * Return a set of vertex indices contained in an array of bonds.\r\n * \r\n * @param {Array} bonds An array of bonds. A bond is defined as [ sourceVertexId, targetVertexId ].\r\n * @returns {Set} An array of vertices.\r\n */\r\n static bondsToAtoms(bonds) {\r\n let atoms = new Set();\r\n\r\n var i = bonds.length;\r\n while (i--) {\r\n atoms.add(bonds[i][0]);\r\n atoms.add(bonds[i][1]);\r\n }\r\n return atoms;\r\n }\r\n\r\n /**\r\n * Returns the number of bonds within a set of atoms.\r\n * \r\n * @param {Set} atoms An array of atom ids.\r\n * @param {Array[]} adjacencyMatrix An adjacency matrix.\r\n * @returns {Number} The number of bonds in a set of atoms.\r\n */\r\n static getBondCount(atoms, adjacencyMatrix) {\r\n let count = 0;\r\n for (let u of atoms) {\r\n for (let v of atoms) {\r\n if (u === v) {\r\n continue;\r\n }\r\n count += adjacencyMatrix[u][v]\r\n }\r\n }\r\n\r\n return count / 2;\r\n }\r\n\r\n /**\r\n * Checks whether or not a given path already exists in an array of paths.\r\n * \r\n * @param {Set[]} pathSets An array of sets each representing a path.\r\n * @param {Set} pathSet A set representing a path.\r\n * @param {Array[]} bonds The bonds associated with the current path.\r\n * @param {Array[]} allBonds All bonds currently associated with rings in the SSSR set.\r\n * @param {Uint16Array} arrBondCount A matrix containing the bond count of each vertex.\r\n * @param {Uint16Array} arrRingCount A matrix containing the number of rings associated with each vertex.\r\n * @returns {Boolean} A boolean indicating whether or not a give path is contained within a set.\r\n */\r\n static pathSetsContain(pathSets, pathSet, bonds, allBonds, arrBondCount, arrRingCount) {\r\n var i = pathSets.length;\r\n while (i--) {\r\n if (SSSR.isSupersetOf(pathSet, pathSets[i])) {\r\n return true;\r\n }\r\n\r\n if (pathSets[i].size !== pathSet.size) {\r\n continue;\r\n }\r\n\r\n if (SSSR.areSetsEqual(pathSets[i], pathSet)) {\r\n return true;\r\n }\r\n }\r\n\r\n // Check if the edges from the candidate are already all contained within the paths of the set of paths.\r\n // TODO: For some reason, this does not replace the isSupersetOf method above -> why?\r\n let count = 0;\r\n let allContained = false;\r\n i = bonds.length;\r\n while (i--) {\r\n var j = allBonds.length;\r\n while (j--) {\r\n if (bonds[i][0] === allBonds[j][0] && bonds[i][1] === allBonds[j][1] ||\r\n bonds[i][1] === allBonds[j][0] && bonds[i][0] === allBonds[j][1]) {\r\n count++;\r\n }\r\n\r\n if (count === bonds.length) {\r\n allContained = true;\r\n }\r\n }\r\n }\r\n\r\n // If all the bonds and thus vertices are already contained within other rings\r\n // check if there's one vertex with ringCount < bondCount\r\n let specialCase = false;\r\n if (allContained) {\r\n for (let element of pathSet) {\r\n if (arrRingCount[element] < arrBondCount[element]) {\r\n specialCase = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (allContained && !specialCase) {\r\n return true;\r\n }\r\n\r\n // Update the ring counts for the vertices\r\n for (let element of pathSet) {\r\n arrRingCount[element]++;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /**\r\n * Checks whether or not two sets are equal (contain the same elements).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not the two sets are equal.\r\n */\r\n static areSetsEqual(setA, setB) {\r\n if (setA.size !== setB.size) {\r\n return false;\r\n }\r\n\r\n for (let element of setA) {\r\n if (!setB.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Checks whether or not a set (setA) is a superset of another set (setB).\r\n * \r\n * @param {Set} setA A set.\r\n * @param {Set} setB A set.\r\n * @returns {Boolean} A boolean indicating whether or not setB is a superset of setA.\r\n */\r\n static isSupersetOf(setA, setB) {\r\n for (var element of setB) {\r\n if (!setA.has(element)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\nmodule.exports = SSSR;","//@ts-check\r\n\r\nclass SequenceType {\r\n\r\n static get VALUES() {\r\n return {\r\n LINEAR: \"linear\",\r\n CYCLIC: \"cyclic\",\r\n BRANCH: \"branched\",\r\n BRANCH_CYCLIC: \"branch-cyclic\",\r\n LINEAR_POLYKETIDE: \"linear-polyketide\",\r\n CYCLIC_POLYKETIDE: \"cyclic-polyketide\",\r\n OTHER: \"other\",\r\n }\r\n }\r\n\r\n static getTypeFromValues(isCyclic, isBranch, isOther) {\r\n if (isOther) { return this.VALUES.OTHER;}\r\n if (!isCyclic && !isBranch) {\r\n return this.VALUES.LINEAR;\r\n } else if(isCyclic && !isBranch) {\r\n return this.VALUES.CYCLIC;\r\n } else if (!isCyclic) {\r\n return this.VALUES.BRANCH;\r\n } else {\r\n return this.VALUES.BRANCH_CYCLIC;\r\n }\r\n }\r\n\r\n}\r\n\r\nmodule.exports = SequenceType;\r\n","//@ts-check\r\nconst Node = require('./Node');\r\nconst SequenceType = require('./SequenceType');\r\nconst VertexState = require('./VertexState');\r\nconst Neighbour = require('./Neighbour');\r\nconst Direction = require('./Direction');\r\n\r\nclass SmallGraph {\r\n\r\n constructor() {\r\n this._nodes = [];\r\n this.isOther = false;\r\n this._branch = false;\r\n this.isCyclic = false;\r\n this.isBranched = false;\r\n this.sequenceType = SequenceType.VALUES.LINEAR;\r\n this._nodeOnRing = null;\r\n }\r\n\r\n addVertex(node) {\r\n this._nodes.push(node);\r\n }\r\n\r\n addNeighbour(nodeId, neighbour, direction) {\r\n this._nodes[nodeId].addNeighbour(new Neighbour(neighbour, direction));\r\n }\r\n\r\n dfsInitialization() {\r\n this._nodes.forEach(e => e.vertexState = VertexState.VALUES.NOT_FOUND);\r\n }\r\n\r\n getSourceNode() {\r\n let ends = [];\r\n for (let index = 0; index < this._nodes.length; ++index) {\r\n if (this._nodes[index].neighbours.length === 1) {\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.C) {\r\n return this._nodes[index];\r\n }\r\n if (this._nodes[index].neighbours[0].direction === Direction.VALUES.POLYKETIDE) {\r\n return this._nodes[index];\r\n }\r\n ends.push(this._nodes[index]);\r\n }\r\n }\r\n if (ends.length > 0) {\r\n return ends[0];\r\n }\r\n return null;\r\n }\r\n\r\n oneCyclic() {\r\n if (this._nodes.length === 0) {\r\n return false;\r\n }\r\n this.dfsInitialization();\r\n this.isCyclic = false;\r\n if (this._nodes.length === 2 && this._nodes[0].neighbours.length === 2 && this._nodes[1].neighbours.length === 2) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = this._nodes[0];\r\n } else {\r\n this.dfsCyclic(this._nodes[0], -1);\r\n }\r\n }\r\n\r\n dfsCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState === VertexState.VALUES.OPEN) {\r\n this.isCyclic = true;\r\n this._nodeOnRing = vertex;\r\n }\r\n\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n for (let i = 0; i < vertex.neighbours.length; ++i) {\r\n if (vertexFromId !== vertex.neighbours[i].neighbour) {\r\n this.dfsCyclic(this._nodes[vertex.neighbours[i].neighbour], vertex.id);\r\n }\r\n }\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n dfsSequenceStart() {\r\n if (this._nodes.length === 0) {\r\n return;\r\n }\r\n this.dfsInitialization();\r\n this.sequence = \"\";\r\n if (this.isCyclic) {\r\n this.findRing(this._nodeOnRing);\r\n this.dfsSequenceCyclic(this._nodeOnRing);\r\n } else {\r\n let sourceNode = this.getSourceNode();\r\n if (sourceNode !== null) {\r\n this.dfsSequence(this.getSourceNode(), -1);\r\n } else {\r\n this.sequenceType = 'other';\r\n this.isOther = true;\r\n return;\r\n }\r\n }\r\n if (this.sequence.charAt(this.sequence.length - 1) === '-') {\r\n this.sequence = this.sequence.substr(0, this.sequence.length - 1);\r\n }\r\n this.sequenceType = SequenceType.getTypeFromValues(this.isCyclic, this.isBranched, this.isOther);\r\n }\r\n\r\n arrayContainsTimes(array, searchValue, times) {\r\n let cnt = 0;\r\n for (let index = 0; index < array.length; ++index) {\r\n if (array[index].neighbour === searchValue) {\r\n cnt++;\r\n if (cnt === times) {\r\n return true;\r\n }\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n findRing(start) {\r\n let queue = [];\r\n let firstPath = [start.id];\r\n let firstPass = true;\r\n queue.push(firstPath);\r\n while (queue.length !== 0) {\r\n let path = queue.pop();\r\n let last = path[path.length - 1];\r\n let node = this._nodes[last];\r\n if (node.id === start.id && !firstPass) {\r\n if (path.length === 3 && path[0] === path[2] && !this.arrayContainsTimes(this._nodes[path[0]].neighbours, path[1], 2)) {\r\n continue;\r\n }\r\n path.forEach(v => this._nodes[v].onRing = true);\r\n continue;\r\n }\r\n node.neighbours.forEach(\r\n neighbour => {\r\n if (!path.some(e => e === neighbour.neighbour) || neighbour.neighbour === start.id) {\r\n let newPath = [...path];\r\n newPath.push(neighbour.neighbour);\r\n queue.push(newPath);\r\n }\r\n }\r\n );\r\n firstPass = false;\r\n }\r\n }\r\n\r\n sortByRingPreference(array) {\r\n let sortedArray = [...array];\r\n sortedArray.sort((a, b) => {\r\n if (this._nodes[a.neighbour].onRing === this._nodes[b.neighbour].onRing) {\r\n if (a.direction > b.direction) {\r\n return -1;\r\n } else if (a.direction < b.direction) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n } else if (this._nodes[a.neighbour].onRing) {\r\n return 1;\r\n } else {\r\n return -1;\r\n }\r\n });\r\n return sortedArray;\r\n }\r\n\r\n dfsSequenceCyclic(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n let sortedNeighbours = this.sortByRingPreference(vertex.neighbours);\r\n for (let index = 0; index < sortedNeighbours.length; ++index) {\r\n if (vertexFromId === sortedNeighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequenceCyclic(this._nodes[sortedNeighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n\r\n printVertex(vertexId) {\r\n this.sequence += `[${vertexId}]`;\r\n }\r\n\r\n printDash() {\r\n if (']' === this.sequence[this.sequence.length - 1]) {\r\n this.sequence += '-';\r\n }\r\n }\r\n\r\n printLeftBrace(vertex) {\r\n if (vertex.neighbours.length > 2) {\r\n if (this.isBranched) {\r\n this.isOther = true;\r\n }\r\n this.sequence += '\\\\(';\r\n this._branch = true;\r\n this.isBranched = true;\r\n }\r\n }\r\n\r\n printRightBrace() {\r\n if (this._branch) {\r\n this.sequence += '\\\\)';\r\n this._branch = false;\r\n }\r\n }\r\n\r\n dfsSequence(vertex, vertexFromId) {\r\n if (vertex.vertexState !== VertexState.VALUES.NOT_FOUND) {\r\n return;\r\n }\r\n this.printLeftBrace(vertex);\r\n this.printDash();\r\n vertex.vertexState = VertexState.VALUES.OPEN;\r\n this.printVertex(vertex.id);\r\n for (let index = 0; index < vertex.neighbours.length; ++index) {\r\n if (vertexFromId === vertex.neighbours[index].neighbour) {\r\n continue;\r\n }\r\n this.dfsSequence(this._nodes[vertex.neighbours[index].neighbour], vertex.id);\r\n }\r\n this.printRightBrace();\r\n vertex.vertexState = VertexState.VALUES.CLOSED;\r\n }\r\n}\r\n\r\nmodule.exports = SmallGraph;\r\n","// we use the drawer to do all the preprocessing. then we take over the drawing\r\n// portion to output to svg\r\nconst ArrayHelper = require('./ArrayHelper');\r\nconst Atom = require('./Atom');\r\nconst Drawer = require('./Drawer');\r\nconst Graph = require('./Graph');\r\nconst Line = require('./Line');\r\nconst SvgWrapper = require('./SvgWrapper');\r\nconst ThemeManager = require('./ThemeManager');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgDrawer {\r\n constructor(options) {\r\n this.preprocessor = new Drawer(options);\r\n }\r\n\r\n /**\r\n * Draws the parsed smiles data to an svg element.\r\n *\r\n * @param {Object} data The tree returned by the smiles parser.\r\n * @param {(String|HTMLElement)} target The id of the HTML svg element the structure is drawn to - or the element itself.\r\n * @param {String} themeName='dark' The name of the theme to use. Built-in themes are 'light' and 'dark'.\r\n * @param {Boolean} infoOnly=false Only output info on the molecule without drawing anything to the canvas.\r\n\r\n * @returns {Oject} The dimensions of the drawing in { width, height }\r\n */\r\n draw(data, target, themeName = 'light', infoOnly = false) {\r\n let preprocessor = this.preprocessor;\r\n\r\n preprocessor.initDraw(data, themeName, infoOnly);\r\n\r\n if (!infoOnly) {\r\n this.themeManager = new ThemeManager(this.preprocessor.opts.themes, themeName);\r\n this.svgWrapper = new SvgWrapper(this.themeManager, target, this.preprocessor.opts);\r\n }\r\n\r\n preprocessor.processGraph();\r\n\r\n // Set the canvas to the appropriate size\r\n this.svgWrapper.determineDimensions(preprocessor.graph.vertices);\r\n\r\n // Do the actual drawing\r\n this.drawEdges(preprocessor.opts.debug);\r\n this.drawVertices(preprocessor.opts.debug);\r\n\r\n if (preprocessor.opts.debug) {\r\n console.log(preprocessor.graph);\r\n console.log(preprocessor.rings);\r\n console.log(preprocessor.ringConnections);\r\n }\r\n\r\n return this.svgWrapper.constructSvg();\r\n }\r\n\r\n /**\r\n * Draws a ring inside a provided ring, indicating aromaticity.\r\n *\r\n * @param {Ring} ring A ring.\r\n */\r\n drawAromaticityRing(ring) {\r\n let ctx = this.ctx;\r\n let radius = MathHelper.apothemFromSideLength(this.opts.bondLength, ring.getSize());\r\n\r\n ctx.save();\r\n ctx.strokeStyle = this.getColor('C');\r\n ctx.lineWidth = this.opts.bondThickness;\r\n ctx.beginPath();\r\n ctx.arc(ring.center.x + this.offsetX, ring.center.y + this.offsetY,\r\n radius - this.opts.bondSpacing, 0, Math.PI * 2, true);\r\n ctx.closePath();\r\n ctx.stroke();\r\n ctx.restore();\r\n }\r\n\r\n /**\r\n * Draw the actual edges as bonds.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdges(debug) {\r\n let preprocessor = this.preprocessor,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n drawn = Array(this.preprocessor.graph.edges.length);\r\n\r\n drawn.fill(false);\r\n\r\n graph.traverseBF(0, vertex => {\r\n let edges = graph.getEdges(vertex.id);\r\n for (var i = 0; i < edges.length; i++) {\r\n let edgeId = edges[i];\r\n if (!drawn[edgeId]) {\r\n drawn[edgeId] = true;\r\n this.drawEdge(edgeId, debug);\r\n }\r\n }\r\n });\r\n\r\n // Draw ring for implicitly defined aromatic rings\r\n if (!this.bridgedRing) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let ring = rings[i];\r\n\r\n if (preprocessor.isRingAromatic(ring)) {\r\n this.drawAromaticityRing(ring);\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Draw the an edge as a bond.\r\n *\r\n * @param {Number} edgeId An edge id.\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug helpers.\r\n */\r\n drawEdge(edgeId, debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n svgWrapper = this.svgWrapper,\r\n edge = preprocessor.graph.edges[edgeId],\r\n vertexA = preprocessor.graph.vertices[edge.sourceId],\r\n vertexB = preprocessor.graph.vertices[edge.targetId],\r\n elementA = vertexA.value.element,\r\n elementB = vertexB.value.element;\r\n\r\n if ((!vertexA.value.isDrawn || !vertexB.value.isDrawn) && preprocessor.opts.atomVisualization === 'default') {\r\n return;\r\n }\r\n\r\n let a = vertexA.position,\r\n b = vertexB.position,\r\n normals = preprocessor.getEdgeNormals(edge),\r\n // Create a point on each side of the line\r\n sides = ArrayHelper.clone(normals);\r\n\r\n sides[0].multiplyScalar(10).add(a);\r\n sides[1].multiplyScalar(10).add(a);\r\n\r\n if (edge.bondType === '=' || preprocessor.getRingbondType(vertexA, vertexB) === '=' ||\r\n (edge.isPartOfAromaticRing && preprocessor.bridgedRing)) {\r\n // Always draw double bonds inside the ring\r\n let inRing = preprocessor.areVerticesInSameRing(vertexA, vertexB);\r\n let s = preprocessor.chooseSide(vertexA, vertexB, sides);\r\n\r\n if (inRing) {\r\n // Always draw double bonds inside a ring\r\n // if the bond is shared by two rings, it is drawn in the larger\r\n // problem: smaller ring is aromatic, bond is still drawn in larger -> fix this\r\n let lcr = preprocessor.getLargestOrAromaticCommonRing(vertexA, vertexB);\r\n let center = lcr.center;\r\n\r\n normals[0].multiplyScalar(opts.bondSpacing);\r\n normals[1].multiplyScalar(opts.bondSpacing);\r\n\r\n // Choose the normal that is on the same side as the center\r\n let line = null;\r\n\r\n if (center.sameSideAs(vertexA.position, vertexB.position, Vector2.add(a, normals[0]))) {\r\n line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n } else {\r\n line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n }\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n // The shortened edge\r\n if (edge.isPartOfAromaticRing) {\r\n // preprocessor.canvasWrapper.drawLine(line, true);\r\n svgWrapper.drawLine(line, true);\r\n } else {\r\n // preprocessor.canvasWrapper.drawLine(line);\r\n svgWrapper.drawLine(line);\r\n }\r\n\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((edge.center || vertexA.isTerminal() && vertexB.isTerminal()) ||\r\n (s.anCount == 0 && s.bnCount > 1 || s.bnCount == 0 && s.anCount > 1)) {\r\n this.multiplyNormals(normals, opts.halfBondSpacing);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB),\r\n lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n } else if ((s.sideCount[0] > s.sideCount[1]) ||\r\n (s.totalSideCount[0] > s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if ((s.sideCount[0] < s.sideCount[1]) ||\r\n (s.totalSideCount[0] <= s.totalSideCount[1])) {\r\n this.multiplyNormals(normals, opts.bondSpacing);\r\n\r\n let line = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n line.shorten(opts.bondLength - opts.shortBondLength * opts.bondLength);\r\n svgWrapper.drawLine(line);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n }\r\n } else if (edge.bondType === '#') {\r\n normals[0].multiplyScalar(opts.bondSpacing / 1.5);\r\n normals[1].multiplyScalar(opts.bondSpacing / 1.5);\r\n\r\n let lineA = new Line(Vector2.add(a, normals[0]), Vector2.add(b, normals[0]), elementA, elementB);\r\n let lineB = new Line(Vector2.add(a, normals[1]), Vector2.add(b, normals[1]), elementA, elementB);\r\n\r\n svgWrapper.drawLine(lineA);\r\n svgWrapper.drawLine(lineB);\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB));\r\n } else if (edge.bondType === '.') {\r\n // TODO: Something... maybe... version 2?\r\n } else {\r\n let isChiralCenterA = vertexA.value.isStereoCenter;\r\n let isChiralCenterB = vertexB.value.isStereoCenter;\r\n\r\n if (edge.wedge === 'up') {\r\n svgWrapper.drawWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else if (edge.wedge === 'down') {\r\n svgWrapper.drawDashedWedge(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n } else {\r\n svgWrapper.drawLine(new Line(a, b, elementA, elementB, isChiralCenterA, isChiralCenterB));\r\n }\r\n }\r\n\r\n if (debug) {\r\n let midpoint = Vector2.midpoint(a, b);\r\n svgWrapper.drawDebugText(midpoint.x, midpoint.y, 'e: ' + edgeId);\r\n }\r\n }\r\n\r\n /**\r\n * Draws the vertices representing atoms to the canvas.\r\n *\r\n * @param {Boolean} debug A boolean indicating whether or not to draw debug messages to the canvas.\r\n */\r\n drawVertices(debug) {\r\n let preprocessor = this.preprocessor,\r\n opts = preprocessor.opts,\r\n graph = preprocessor.graph,\r\n rings = preprocessor.rings,\r\n svgWrapper = this.svgWrapper;\r\n\r\n var i = graph.vertices.length;\r\n for (var i = 0; i < graph.vertices.length; i++) {\r\n let vertex = graph.vertices[i];\r\n let atom = vertex.value;\r\n let charge = 0;\r\n let isotope = 0;\r\n let bondCount = vertex.value.bondCount;\r\n let element = atom.element;\r\n let hydrogens = Atom.maxBonds[element] - bondCount;\r\n let dir = vertex.getTextDirection(graph.vertices);\r\n let isTerminal = opts.terminalCarbons || element !== 'C' || atom.hasAttachedPseudoElements ? vertex.isTerminal() : false;\r\n let isCarbon = atom.element === 'C';\r\n\r\n // This is a HACK to remove all hydrogens from nitrogens in aromatic rings, as this\r\n // should be the most common state. This has to be fixed by kekulization\r\n if (atom.element === 'N' && atom.isPartOfAromaticRing) {\r\n hydrogens = 0;\r\n }\r\n\r\n if (atom.bracket) {\r\n hydrogens = atom.bracket.hcount;\r\n charge = atom.bracket.charge;\r\n isotope = atom.bracket.isotope;\r\n }\r\n\r\n if (opts.atomVisualization === 'allballs') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n } else if ((atom.isDrawn && (!isCarbon || atom.drawExplicit || isTerminal || atom.hasAttachedPseudoElements)) || graph.vertices.length === 1) {\r\n if (opts.atomVisualization === 'default') {\r\n svgWrapper.drawText(vertex.position.x, vertex.position.y,\r\n element, hydrogens, dir, isTerminal, charge, isotope, atom.getAttachedPseudoElements());\r\n } else if (opts.atomVisualization === 'balls') {\r\n svgWrapper.drawBall(vertex.position.x, vertex.position.y, element);\r\n }\r\n } else if (vertex.getNeighbourCount() === 2 && vertex.forcePositioned == true) {\r\n // If there is a carbon which bonds are in a straight line, draw a dot\r\n let a = graph.vertices[vertex.neighbours[0]].position;\r\n let b = graph.vertices[vertex.neighbours[1]].position;\r\n let angle = Vector2.threePointangle(vertex.position, a, b);\r\n\r\n if (Math.abs(Math.PI - angle) < 0.1) {\r\n svgWrapper.drawPoint(vertex.position.x, vertex.position.y, element);\r\n }\r\n }\r\n\r\n if (debug) {\r\n let value = 'v: ' + vertex.id + ' ' + ArrayHelper.print(atom.ringbonds);\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, value);\r\n } else {\r\n svgWrapper.drawDebugText(vertex.position.x, vertex.position.y, vertex.value.chirality);\r\n }\r\n }\r\n\r\n // Draw the ring centers for debug purposes\r\n if (opts.debug) {\r\n for (var i = 0; i < rings.length; i++) {\r\n let center = rings[i].center;\r\n svgWrapper.drawDebugPoint(center.x, center.y, 'r: ' + rings[i].id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Returns the total overlap score of the current molecule.\r\n *\r\n * @returns {Number} The overlap score.\r\n */\r\n getTotalOverlapScore() {\r\n return this.preprocessor.getTotalOverlapScore();\r\n }\r\n\r\n /**\r\n * Returns the molecular formula of the loaded molecule as a string.\r\n *\r\n * @returns {String} The molecular formula.\r\n */\r\n getMolecularFormula() {\r\n return this.preprocessor.getMolecularFormula();\r\n }\r\n\r\n /**\r\n * @param {Array} normals list of normals to multiply\r\n * @param {Number} spacing value to multiply normals by\r\n */\r\n multiplyNormals(normals, spacing) {\r\n normals[0].multiplyScalar(spacing);\r\n normals[1].multiplyScalar(spacing);\r\n }\r\n}\r\n\r\nmodule.exports = SvgDrawer;","const {\r\n getChargeText\r\n} = require('./UtilityFunctions');\r\n\r\nconst Line = require('./Line');\r\nconst Vector2 = require('./Vector2');\r\n\r\nclass SvgWrapper {\r\n constructor(themeManager, target, options) {\r\n this.svg = document.getElementById(target);\r\n this.opts = options;\r\n this.gradientId = 0;\r\n\r\n // maintain a list of line elements and their corresponding gradients\r\n // maintain a list of vertex elements\r\n this.paths = [];\r\n this.vertices = [];\r\n this.gradients = [];\r\n\r\n // maintain the offset for drawing purposes\r\n this.offsetX = 0.0;\r\n this.offsetY = 0.0;\r\n\r\n // maintain the dimensions\r\n this.drawingWidth = 0;\r\n this.drawingHeight = 0;\r\n this.halfBondThickness = this.opts.bondThickness / 2.0;\r\n\r\n // for managing color schemes\r\n this.themeManager = themeManager;\r\n\r\n // create the mask\r\n this.maskElements = [];\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'rect');\r\n mask.setAttributeNS(null, 'x', 0);\r\n mask.setAttributeNS(null, 'y', 0);\r\n mask.setAttributeNS(null, 'width', '100%');\r\n mask.setAttributeNS(null, 'height', '100%');\r\n mask.setAttributeNS(null, 'fill', 'white');\r\n\r\n this.maskElements.push(mask);\r\n\r\n // clear the svg element\r\n while (this.svg.firstChild) {\r\n this.svg.removeChild(this.svg.firstChild);\r\n }\r\n }\r\n\r\n constructSvg() {\r\n // TODO: add the defs element to put gradients in\r\n let defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs'),\r\n masks = document.createElementNS('http://www.w3.org/2000/svg', 'mask'),\r\n style = document.createElementNS('http://www.w3.org/2000/svg', 'style'),\r\n paths = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n vertices = document.createElementNS('http://www.w3.org/2000/svg', 'g'),\r\n pathChildNodes = this.paths;\r\n\r\n // give the mask an id\r\n masks.setAttributeNS(null, 'id', 'text-mask');\r\n\r\n // create the css styles\r\n style.appendChild(document.createTextNode(`\r\n .element {\r\n font: ${this.opts.fontSizeLarge}pt Helvetica, Arial, sans-serif;\r\n alignment-baseline: 'middle';\r\n }\r\n .sub {\r\n font: ${this.opts.fontSizeSmall}pt Helvetica, Arial, sans-serif;\r\n }\r\n `));\r\n\r\n for (let path of pathChildNodes) {\r\n paths.appendChild(path);\r\n }\r\n for (let vertex of this.vertices) {\r\n vertices.appendChild(vertex);\r\n }\r\n for (let mask of this.maskElements) {\r\n masks.appendChild(mask);\r\n }\r\n for (let gradient of this.gradients) {\r\n defs.appendChild(gradient);\r\n }\r\n\r\n paths.setAttributeNS(null, 'mask', 'url(#text-mask)');\r\n\r\n if (this.svg) {\r\n this.svg.appendChild(defs);\r\n this.svg.appendChild(masks);\r\n this.svg.appendChild(style);\r\n this.svg.appendChild(paths);\r\n this.svg.appendChild(vertices);\r\n return this.svg;\r\n } else {\r\n let container = document.createElementNS('http://www.w3.org/2000/svg', 'g');\r\n container.appendChild(defs);\r\n container.appendChild(masks);\r\n container.appendChild(style);\r\n container.appendChild(paths);\r\n container.appendChild(vertices);\r\n return container;\r\n }\r\n }\r\n\r\n /**\r\n * Create a linear gradient to apply to a line\r\n *\r\n * @param {Line} line the line to apply the gradiation to.\r\n */\r\n createGradient(line) {\r\n // create the gradient and add it\r\n let gradient = document.createElementNS('http://www.w3.org/2000/svg', 'linearGradient'),\r\n gradientUrl = `line-${this.gradientId++}`,\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n gradient.setAttributeNS(null, 'id', gradientUrl);\r\n gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');\r\n gradient.setAttributeNS(null, 'x1', fromX);\r\n gradient.setAttributeNS(null, 'y1', fromY);\r\n gradient.setAttributeNS(null, 'x2', toX);\r\n gradient.setAttributeNS(null, 'y2', toY);\r\n\r\n let firstStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n firstStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getLeftElement()) || this.themeManager.getColor('C'));\r\n firstStop.setAttributeNS(null, 'offset', '20%');\r\n\r\n let secondStop = document.createElementNS('http://www.w3.org/2000/svg', 'stop');\r\n secondStop.setAttributeNS(null, 'stop-color', this.themeManager.getColor(line.getRightElement() || this.themeManager.getColor('C')));\r\n secondStop.setAttributeNS(null, 'offset', '100%');\r\n\r\n gradient.appendChild(firstStop);\r\n gradient.appendChild(secondStop);\r\n\r\n this.gradients.push(gradient);\r\n\r\n return gradientUrl;\r\n }\r\n\r\n /**\r\n * Create a tspan element for sub or super scripts that styles the text\r\n * appropriately as one of those text types.\r\n *\r\n * @param {String} text the actual text\r\n * @param {String} shift the type of text, either 'sub', or 'super'\r\n */\r\n createSubSuperScripts(text, shift) {\r\n let elem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n elem.setAttributeNS(null, 'baseline-shift', shift);\r\n elem.appendChild(document.createTextNode(text));\r\n elem.setAttributeNS(null, 'class', 'sub');\r\n\r\n return elem;\r\n }\r\n\r\n /**\r\n * Determine drawing dimensiosn based on vertex positions.\r\n *\r\n * @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.\r\n */\r\n determineDimensions(vertices) {\r\n // Figure out the final size of the image\r\n let maxX = -Number.MAX_VALUE;\r\n let maxY = -Number.MAX_VALUE;\r\n let minX = Number.MAX_VALUE;\r\n let minY = Number.MAX_VALUE;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n if (!vertices[i].value.isDrawn) {\r\n continue;\r\n }\r\n\r\n let p = vertices[i].position;\r\n\r\n if (maxX < p.x) maxX = p.x;\r\n if (maxY < p.y) maxY = p.y;\r\n if (minX > p.x) minX = p.x;\r\n if (minY > p.y) minY = p.y;\r\n }\r\n\r\n // Add padding\r\n let padding = this.opts.padding;\r\n maxX += padding;\r\n maxY += padding;\r\n minX -= padding;\r\n minY -= padding;\r\n\r\n this.drawingWidth = maxX - minX;\r\n this.drawingHeight = maxY - minY;\r\n\r\n let scaleX = this.svg.clientWidth / this.drawingWidth;\r\n let scaleY = this.svg.clientHeight / this.drawingHeight;\r\n\r\n let scale = (scaleX < scaleY) ? scaleX : scaleY;\r\n let viewBoxDim = Math.round(this.drawingWidth > this.drawingHeight ? this.drawingWidth : this.drawingHeight);\r\n\r\n this.svg.setAttributeNS(null, 'viewBox', `0 0 ${viewBoxDim} ${viewBoxDim}`);\r\n\r\n this.offsetX = -minX;\r\n this.offsetY = -minY;\r\n\r\n // Center\r\n if (scaleX < scaleY) {\r\n this.offsetY += this.svg.clientHeight / (2.0 * scale) - this.drawingHeight / 2.0;\r\n } else {\r\n this.offsetX += this.svg.clientWidth / (2.0 * scale) - this.drawingWidth / 2.0;\r\n }\r\n }\r\n\r\n /**\r\n * Draw an svg ellipse as a ball.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawBall(x, y, elementName) {\r\n let ball = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n ball.setAttributeNS(null, 'cx', x + this.offsetX);\r\n ball.setAttributeNS(null, 'cy', y + this.offsetY);\r\n ball.setAttributeNS(null, 'r', this.opts.bondLength / 4.5);\r\n ball.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n\r\n this.vertices.push(ball);\r\n }\r\n\r\n /**\r\n * Draw a dashed wedge on the canvas.\r\n *\r\n * @param {Line} line A line.\r\n */\r\n drawDashedWedge(line) {\r\n if (isNaN(line.from.x) || isNaN(line.from.y) ||\r\n isNaN(line.to.x) || isNaN(line.to.y)) {\r\n return;\r\n }\r\n\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone(),\r\n normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral(),\r\n start,\r\n end;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n } else {\r\n start = l;\r\n end = r;\r\n }\r\n\r\n let dir = Vector2.subtract(end, start).normalize(),\r\n length = line.getLength(),\r\n step = 1.25 / (length / (this.opts.bondThickness * 3.0)),\r\n changed = false;\r\n\r\n let gradient = this.createGradient(line);\r\n\r\n for (let t = 0.0; t < 1.0; t += step) {\r\n let to = Vector2.multiplyScalar(dir, t * length),\r\n startDash = Vector2.add(start, to),\r\n width = 1.5 * t,\r\n dashOffset = Vector2.multiplyScalar(normals[0], width);\r\n\r\n startDash.subtract(dashOffset);\r\n let endDash = startDash.clone();\r\n endDash.add(Vector2.multiplyScalar(dashOffset, 2.0));\r\n\r\n this.drawLine(new Line(startDash, endDash), null, gradient);\r\n }\r\n }\r\n\r\n /**\r\n * Draws a debug dot at a given coordinate and adds text.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordindate.\r\n * @param {String} [debugText=''] A string.\r\n * @param {String} [color='#f00'] A color in hex form.\r\n */\r\n drawDebugPoint(x, y, debugText = '', color = '#f00') {\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + this.offsetX);\r\n point.setAttributeNS(null, 'cy', y + this.offsetY);\r\n point.setAttributeNS(null, 'r', '2');\r\n point.setAttributeNS(null, 'fill', '#f00');\r\n this.vertices.push(point);\r\n this.drawDebugText(x, y, debugText);\r\n }\r\n\r\n /**\r\n * Draws a debug text message at a given position\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {String} text The debug text.\r\n */\r\n drawDebugText(x, y, text) {\r\n let textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text');\r\n textElem.setAttributeNS(null, 'x', x + this.offsetX);\r\n textElem.setAttributeNS(null, 'y', y + this.offsetY);\r\n textElem.setAttributeNS(null, 'class', 'debug');\r\n textElem.setAttributeNS(null, 'fill', '#ff0000');\r\n textElem.setAttributeNS(null, 'style', `\r\n font: 5px Droid Sans, sans-serif;\r\n `);\r\n textElem.appendChild(document.createTextNode(text));\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * Draws a line.\r\n *\r\n * @param {Line} line A line.\r\n * @param {Boolean} dashed defaults to false.\r\n * @param {String} gradient gradient url. Defaults to null.\r\n */\r\n drawLine(line, dashed = false, gradient = null) {\r\n let opts = this.opts,\r\n stylesArr = [\r\n ['stroke-linecap', 'round'],\r\n ['stroke-dasharray', dashed ? '5, 5' : 'none'],\r\n ],\r\n l = line.getLeftVector(),\r\n r = line.getRightVector(),\r\n fromX = l.x + this.offsetX,\r\n fromY = l.y + this.offsetY,\r\n toX = r.x + this.offsetX,\r\n toY = r.y + this.offsetY;\r\n\r\n let styles = stylesArr.map(sub => sub.join(':')).join(';'),\r\n lineElem = document.createElementNS('http://www.w3.org/2000/svg', 'line');\r\n\r\n lineElem.setAttributeNS(null, 'x1', fromX);\r\n lineElem.setAttributeNS(null, 'y1', fromY);\r\n lineElem.setAttributeNS(null, 'x2', toX);\r\n lineElem.setAttributeNS(null, 'y2', toY);\r\n lineElem.setAttributeNS(null, 'style', styles);\r\n this.paths.push(lineElem);\r\n\r\n if (gradient == null) {\r\n gradient = this.createGradient(line, fromX, fromY, toX, toY);\r\n }\r\n lineElem.setAttributeNS(null, 'stroke', `url('#${gradient}')`);\r\n }\r\n\r\n /**\r\n * Draw a point.\r\n *\r\n * @param {Number} x The x position of the point.\r\n * @param {Number} y The y position of the point.\r\n * @param {String} elementName The name of the element (single-letter).\r\n */\r\n drawPoint(x, y, elementName) {\r\n let ctx = this.ctx;\r\n let offsetX = this.offsetX;\r\n let offsetY = this.offsetY;\r\n\r\n // first create a mask\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', x + offsetX);\r\n mask.setAttributeNS(null, 'cy', y + offsetY);\r\n mask.setAttributeNS(null, 'r', '1.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // now create the point\r\n let point = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n point.setAttributeNS(null, 'cx', x + offsetX);\r\n point.setAttributeNS(null, 'cy', y + offsetY);\r\n point.setAttributeNS(null, 'r', '0.75');\r\n point.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n this.vertices.push(point);\r\n }\r\n\r\n /**\r\n * Draw a text to the canvas.\r\n *\r\n * @param {Number} x The x position of the text.\r\n * @param {Number} y The y position of the text.\r\n * @param {String} elementName The name of the element (single-letter).\r\n * @param {Number} hydrogens The number of hydrogen atoms.\r\n * @param {String} direction The direction of the text in relation to the associated vertex.\r\n * @param {Boolean} isTerminal A boolean indicating whether or not the vertex is terminal.\r\n * @param {Number} charge The charge of the atom.\r\n * @param {Number} isotope The isotope number.\r\n * @param {Object} attachedPseudoElement A map with containing information for pseudo elements or concatinated elements. The key is comprised of the element symbol and the hydrogen count.\r\n * @param {String} attachedPseudoElement.element The element symbol.\r\n * @param {Number} attachedPseudoElement.count The number of occurences that match the key.\r\n * @param {Number} attachedPseudoElement.hyrogenCount The number of hydrogens attached to each atom matching the key.\r\n */\r\n drawText(x, y, elementName, hydrogens, direction, isTerminal, charge, isotope, attachedPseudoElement = {}) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n pos = {\r\n x: x + offsetX,\r\n y: y + offsetY,\r\n },\r\n textElem = document.createElementNS('http://www.w3.org/2000/svg', 'text'),\r\n writingMode = 'horizontal-tb',\r\n letterSpacing = 'normal',\r\n textOrientation = 'mixed',\r\n textDirection = 'direction: ltr;',\r\n xShift = -2,\r\n yShift = 2.5;\r\n\r\n let mask = document.createElementNS('http://www.w3.org/2000/svg', 'circle');\r\n mask.setAttributeNS(null, 'cx', pos.x);\r\n mask.setAttributeNS(null, 'cy', pos.y);\r\n mask.setAttributeNS(null, 'r', '3.5');\r\n mask.setAttributeNS(null, 'fill', 'black');\r\n this.maskElements.push(mask);\r\n\r\n // determine writing mode\r\n if (/up|down/.test(direction) && !isTerminal) {\r\n writingMode = 'vertical-rl';\r\n textOrientation = 'upright';\r\n letterSpacing = '-1px';\r\n }\r\n\r\n if (direction === 'down' && !isTerminal) {\r\n xShift = 0;\r\n yShift = -2;\r\n } else if (direction === 'up' && !isTerminal) {\r\n xShift = 0.5;\r\n } else if (direction === 'left') {\r\n xShift = 2;\r\n }\r\n\r\n if (direction === 'left' || (direction === 'up' && !isTerminal)) {\r\n textDirection = 'direction: rtl; unicode-bidi: bidi-override;'\r\n }\r\n\r\n // now the text element\r\n textElem.setAttributeNS(null, 'x', pos.x + xShift);\r\n textElem.setAttributeNS(null, 'y', pos.y + yShift);\r\n textElem.setAttributeNS(null, 'class', 'element');\r\n textElem.setAttributeNS(null, 'fill', this.themeManager.getColor(elementName));\r\n textElem.setAttributeNS(null, 'style', `\r\n text-anchor: start;\r\n writing-mode: ${writingMode};\r\n text-orientation: ${textOrientation};\r\n letter-spacing: ${letterSpacing};\r\n ${textDirection}\r\n `);\r\n\r\n let textNode = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n // special case for element names that are 2 letters\r\n if (elementName.length > 1) {\r\n let textAnchor = /up|down/.test(direction) ? 'middle' : 'start';\r\n\r\n textNode.setAttributeNS(null, 'style', `\r\n unicode-bidi: plaintext;\r\n writing-mode: lr-tb;\r\n letter-spacing: normal;\r\n text-anchor: ${textAnchor};\r\n `);\r\n }\r\n textNode.appendChild(document.createTextNode(elementName));\r\n textElem.appendChild(textNode);\r\n\r\n // Charge\r\n if (charge) {\r\n let chargeElem = this.createSubSuperScripts(getChargeText(charge), 'super');\r\n textNode.appendChild(chargeElem);\r\n }\r\n\r\n let isotopeText = '0';\r\n\r\n if (isotope > 0) {\r\n let isotopeElem = this.createSubSuperScripts(isotope.toString(), 'super');\r\n textNode.appendChild(isotopeElem);\r\n }\r\n\r\n\r\n // TODO: Better handle exceptions\r\n // Exception for nitro (draw nitro as NO2 instead of N+O-O)\r\n if (charge === 1 && elementName === 'N' && attachedPseudoElement.hasOwnProperty('0O') &&\r\n attachedPseudoElement.hasOwnProperty('0O-1')) {\r\n attachedPseudoElement = {\r\n '0O': {\r\n element: 'O',\r\n count: 2,\r\n hydrogenCount: 0,\r\n previousElement: 'C',\r\n charge: ''\r\n }\r\n }\r\n charge = 0;\r\n }\r\n\r\n if (hydrogens > 0) {\r\n let hydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n hydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n hydrogenElem.appendChild(document.createTextNode('H'));\r\n textElem.appendChild(hydrogenElem);\r\n\r\n if (hydrogens > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogens, 'sub');\r\n hydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n for (let key in attachedPseudoElement) {\r\n if (!attachedPseudoElement.hasOwnProperty(key)) {\r\n continue;\r\n }\r\n\r\n let element = attachedPseudoElement[key].element,\r\n elementCount = attachedPseudoElement[key].count,\r\n hydrogenCount = attachedPseudoElement[key].hydrogenCount,\r\n elementCharge = attachedPseudoElement[key].charge,\r\n pseudoElementElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoElementElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoElementElem.appendChild(document.createTextNode(element));\r\n pseudoElementElem.setAttributeNS(null, 'fill', this.themeManager.getColor(element));\r\n\r\n if (elementCharge !== 0) {\r\n let elementChargeElem = this.createSubSuperScripts(getChargeText(elementCharge), 'super');\r\n pseudoElementElem.appendChild(elementChargeElem);\r\n }\r\n\r\n if (hydrogenCount > 0) {\r\n let pseudoHydrogenElem = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');\r\n\r\n pseudoHydrogenElem.setAttributeNS(null, 'style', 'unicode-bidi: plaintext;');\r\n pseudoHydrogenElem.appendChild(document.createTextNode('H'));\r\n pseudoElementElem.appendChild(pseudoHydrogenElem);\r\n\r\n if (hydrogenCount > 1) {\r\n let hydrogenCountElem = this.createSubSuperScripts(hydrogenCount, 'sub');\r\n pseudoHydrogenElem.appendChild(hydrogenCountElem);\r\n }\r\n }\r\n\r\n if (elementCount > 1) {\r\n let elementCountElem = this.createSubSuperScripts(elementCount, 'sub');\r\n pseudoElementElem.appendChild(elementCountElem);\r\n }\r\n\r\n textElem.appendChild(pseudoElementElem);\r\n }\r\n\r\n this.vertices.push(textElem);\r\n }\r\n\r\n /**\r\n * @param {Line} line the line object to create the wedge from\r\n */\r\n drawWedge(line) {\r\n let offsetX = this.offsetX,\r\n offsetY = this.offsetY,\r\n l = line.getLeftVector().clone(),\r\n r = line.getRightVector().clone();\r\n\r\n l.x += offsetX;\r\n l.y += offsetY;\r\n\r\n r.x += offsetX;\r\n r.y += offsetY;\r\n\r\n let normals = Vector2.normals(l, r);\r\n\r\n normals[0].normalize();\r\n normals[1].normalize();\r\n\r\n let isRightChiralCenter = line.getRightChiral();\r\n\r\n let start = l,\r\n end = r;\r\n\r\n if (isRightChiralCenter) {\r\n start = r;\r\n end = l;\r\n }\r\n\r\n let t = Vector2.add(start, Vector2.multiplyScalar(normals[0], this.halfBondThickness)),\r\n u = Vector2.add(end, Vector2.multiplyScalar(normals[0], 1.5 + this.halfBondThickness)),\r\n v = Vector2.add(end, Vector2.multiplyScalar(normals[1], 1.5 + this.halfBondThickness)),\r\n w = Vector2.add(start, Vector2.multiplyScalar(normals[1], this.halfBondThickness));\r\n\r\n let polygon = document.createElementNS('http://www.w3.org/2000/svg', 'polygon'),\r\n gradient = this.createGradient(line, l.x, l.y, r.x, r.y);\r\n polygon.setAttributeNS(null, 'points', `${t.x},${t.y} ${u.x},${u.y} ${v.x},${v.y} ${w.x},${w.y}`);\r\n polygon.setAttributeNS(null, 'fill', `url('#${gradient}')`);\r\n this.paths.push(polygon);\r\n }\r\n}\r\n\r\nmodule.exports = SvgWrapper;","class ThemeManager {\r\n constructor(colors, theme) {\r\n this.colors = colors;\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n /**\r\n * Returns the hex code of a color associated with a key from the current theme.\r\n *\r\n * @param {String} key The color key in the theme (e.g. C, N, BACKGROUND, ...).\r\n * @returns {String} A color hex value.\r\n */\r\n getColor(key) {\r\n if (key) {\r\n key = key.toUpperCase();\r\n\r\n if (key in this.theme) {\r\n return this.theme[key];\r\n }\r\n }\r\n\r\n return this.theme['C'];\r\n }\r\n\r\n /**\r\n * Sets the theme to the specified string if it exists. If it does not, this\r\n * does nothing.\r\n *\r\n * @param {String} theme the name of the theme to switch to\r\n */\r\n setTheme(theme) {\r\n if (this.colors.hasOwnProperty(theme)) {\r\n this.theme = this.colors[theme];\r\n }\r\n\r\n // TODO: this probably should notify those who are watching this theme\r\n // manager that the theme has changed so that colors can be changed\r\n // on the fly\r\n }\r\n}\r\n\r\nmodule.exports = ThemeManager;","/**\r\n * Translate the integer indicating the charge to the appropriate text.\r\n * @param {Number} charge The integer indicating the charge.\r\n * @returns {String} A string representing a charge.\r\n */\r\nfunction getChargeText(charge) {\r\n console.log('in the utility version of getChargeText');\r\n if (charge === 1) {\r\n return '+'\r\n } else if (charge === 2) {\r\n return '2+';\r\n } else if (charge === -1) {\r\n return '-';\r\n } else if (charge === -2) {\r\n return '2-';\r\n } else {\r\n return '';\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n getChargeText,\r\n}","//@ts-check\r\n\r\n/** \r\n * A class representing a 2D vector.\r\n * \r\n * @property {Number} x The x component of the vector.\r\n * @property {Number} y The y component of the vector.\r\n */\r\nclass Vector2 {\r\n /**\r\n * The constructor of the class Vector2.\r\n *\r\n * @param {(Number|Vector2)} x The initial x coordinate value or, if the single argument, a Vector2 object.\r\n * @param {Number} y The initial y coordinate value.\r\n */\r\n constructor(x, y) {\r\n if (arguments.length == 0) {\r\n this.x = 0;\r\n this.y = 0;\r\n } else if (arguments.length == 1) {\r\n this.x = x.x;\r\n this.y = x.y;\r\n } else {\r\n this.x = x;\r\n this.y = y;\r\n }\r\n }\r\n\r\n /**\r\n * Clones this vector and returns the clone.\r\n *\r\n * @returns {Vector2} The clone of this vector.\r\n */\r\n clone() {\r\n return new Vector2(this.x, this.y);\r\n }\r\n\r\n /**\r\n * Returns a string representation of this vector.\r\n *\r\n * @returns {String} A string representation of this vector.\r\n */\r\n toString() {\r\n return '(' + this.x + ',' + this.y + ')';\r\n }\r\n\r\n /**\r\n * Add the x and y coordinate values of a vector to the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n add(vec) {\r\n this.x += vec.x;\r\n this.y += vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Subtract the x and y coordinate values of a vector from the x and y coordinate values of this vector.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n subtract(vec) {\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Divide the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n divide(scalar) {\r\n this.x /= scalar;\r\n this.y /= scalar;\r\n\r\n return this;\r\n }\r\n \r\n /**\r\n * Multiply the x and y coordinate values of this vector by the values of another vector.\r\n *\r\n * @param {Vector2} v A vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiply(v) {\r\n this.x *= v.x;\r\n this.y *= v.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Multiply the x and y coordinate values of this vector by a scalar.\r\n *\r\n * @param {Number} scalar The scalar.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n multiplyScalar(scalar) {\r\n this.x *= scalar;\r\n this.y *= scalar;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Inverts this vector. Same as multiply(-1.0).\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n invert() {\r\n this.x = -this.x;\r\n this.y = -this.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vector in relation to the coordinate system.\r\n *\r\n * @returns {Number} The angle in radians.\r\n */\r\n angle() {\r\n return Math.atan2(this.y, this.x);\r\n }\r\n\r\n /**\r\n * Returns the euclidean distance between this vector and another vector.\r\n *\r\n * @param {Vector2} vec A vector.\r\n * @returns {Number} The euclidean distance between the two vectors.\r\n */\r\n distance(vec) {\r\n return Math.sqrt((vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y));\r\n }\r\n\r\n /**\r\n * Returns the squared euclidean distance between this vector and another vector. When only the relative distances of a set of vectors are needed, this is is less expensive than using distance(vec).\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} The squared euclidean distance of the two vectors.\r\n */\r\n distanceSq(vec) {\r\n return (vec.x - this.x) * (vec.x - this.x) + (vec.y - this.y) * (vec.y - this.y);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to the coordinate system.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to the coordinate system.\r\n */\r\n clockwise(vec) {\r\n let a = this.y * vec.x;\r\n let b = this.x * vec.y;\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is in a clockwise or counter-clockwise rotational direction compared to another vector in relation to an arbitrary third vector.\r\n *\r\n * @param {Vector2} center The central vector.\r\n * @param {Vector2} vec Another vector.\r\n * @returns {Number} Returns -1, 0 or 1 if the vector supplied as an argument is clockwise, neutral or counter-clockwise respectively to this vector in relation to an arbitrary third vector.\r\n */\r\n relativeClockwise(center, vec) {\r\n let a = (this.y - center.y) * (vec.x - center.x);\r\n let b = (this.x - center.x) * (vec.y - center.y);\r\n \r\n if (a > b) {\r\n return -1;\r\n }\r\n else if (a === b) {\r\n return 0;\r\n }\r\n\r\n return 1;\r\n }\r\n\r\n /**\r\n * Rotates this vector by a given number of radians around the origin of the coordinate system.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotate(angle) {\r\n let tmp = new Vector2(0, 0);\r\n let cosAngle = Math.cos(angle);\r\n let sinAngle = Math.sin(angle);\r\n\r\n tmp.x = this.x * cosAngle - this.y * sinAngle;\r\n tmp.y = this.x * sinAngle + this.y * cosAngle;\r\n \r\n this.x = tmp.x;\r\n this.y = tmp.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates this vector around another vector.\r\n *\r\n * @param {Number} angle The angle in radians to rotate the vector.\r\n * @param {Vector2} vec The vector which is used as the rotational center.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateAround(angle, vec) {\r\n let s = Math.sin(angle);\r\n let c = Math.cos(angle);\r\n\r\n this.x -= vec.x;\r\n this.y -= vec.y;\r\n\r\n let x = this.x * c - this.y * s;\r\n let y = this.x * s + this.y * c;\r\n\r\n this.x = x + vec.x;\r\n this.y = y + vec.y;\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotate a vector around a given center to the same angle as another vector (so that the two vectors and the center are in a line, with both vectors on one side of the center), keeps the distance from this vector to the center.\r\n *\r\n * @param {Vector2} vec The vector to rotate this vector to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} [offsetAngle=0.0] An additional amount of radians to rotate the vector.\r\n * @returns {Vector2} Returns itself.\r\n */\r\n rotateTo(vec, center, offsetAngle = 0.0) {\r\n // Problem if this is first position\r\n this.x += 0.001;\r\n this.y -= 0.001;\r\n\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n\r\n this.rotateAround(angle + offsetAngle, center);\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Rotates the vector away from a specified vector around a center.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n */\r\n rotateAwayFrom(vec, center, angle) {\r\n this.rotateAround(angle, center);\r\n \r\n let distSqA = this.distanceSq(vec);\r\n \r\n this.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = this.distanceSq(vec);\r\n\r\n // If it was rotated towards the other vertex, rotate in other direction by same amount.\r\n if (distSqB < distSqA) {\r\n this.rotateAround(2.0 * angle, center);\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector away from a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated away from.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateAwayFromAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB < distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Returns the angle in radians used to rotate this vector towards a given vector.\r\n * \r\n * @param {Vector2} vec The vector this one is rotated towards to.\r\n * @param {Vector2} center The rotational center.\r\n * @param {Number} angle The angle by which to rotate.\r\n * @returns {Number} The angle in radians.\r\n */\r\n getRotateTowardsAngle(vec, center, angle) {\r\n let tmp = this.clone();\r\n\r\n tmp.rotateAround(angle, center);\r\n \r\n let distSqA = tmp.distanceSq(vec);\r\n \r\n tmp.rotateAround(-2.0 * angle, center);\r\n\r\n let distSqB = tmp.distanceSq(vec);\r\n\r\n if (distSqB > distSqA) {\r\n return angle;\r\n } else {\r\n return -angle;\r\n }\r\n }\r\n\r\n /**\r\n * Gets the angles between this vector and another vector around a common center of rotation.\r\n *\r\n * @param {Vector2} vec Another vector.\r\n * @param {Vector2} center The center of rotation.\r\n * @returns {Number} The angle between this vector and another vector around a center of rotation in radians.\r\n */\r\n getRotateToAngle(vec, center) {\r\n let a = Vector2.subtract(this, center);\r\n let b = Vector2.subtract(vec, center);\r\n let angle = Vector2.angle(b, a);\r\n \r\n return Number.isNaN(angle) ? 0.0 : angle;\r\n }\r\n\r\n /**\r\n * Checks whether a vector lies within a polygon spanned by a set of vectors.\r\n *\r\n * @param {Vector2[]} polygon An array of vectors spanning the polygon.\r\n * @returns {Boolean} A boolean indicating whether or not this vector is within a polygon.\r\n */\r\n isInPolygon(polygon) {\r\n let inside = false;\r\n\r\n // Its not always a given, that the polygon is convex (-> sugars)\r\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\r\n if (((polygon[i].y > this.y) != (polygon[j].y > this.y)) &&\r\n (this.x < (polygon[j].x - polygon[i].x) * (this.y - polygon[i].y) /\r\n (polygon[j].y - polygon[i].y) + polygon[i].x)) {\r\n inside = !inside;\r\n }\r\n }\r\n\r\n\r\n return inside;\r\n }\r\n\r\n /**\r\n * Returns the length of this vector.\r\n *\r\n * @returns {Number} The length of this vector.\r\n */\r\n length() {\r\n return Math.sqrt((this.x * this.x) + (this.y * this.y));\r\n }\r\n\r\n /**\r\n * Returns the square of the length of this vector.\r\n *\r\n * @returns {Number} The square of the length of this vector.\r\n */\r\n lengthSq() {\r\n return (this.x * this.x) + (this.y * this.y);\r\n }\r\n\r\n /**\r\n * Normalizes this vector.\r\n *\r\n * @returns {Vector2} Returns itself.\r\n */\r\n normalize() {\r\n this.divide(this.length());\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Returns a normalized copy of this vector.\r\n *\r\n * @returns {Vector2} A normalized copy of this vector.\r\n */\r\n normalized() {\r\n return Vector2.divideScalar(this, this.length());\r\n }\r\n\r\n /**\r\n * Calculates which side of a line spanned by two vectors this vector is.\r\n *\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} A number indicating the side of this vector, given a line spanned by two other vectors.\r\n */\r\n whichSide(vecA, vecB) {\r\n return (this.x - vecA.x) * (vecB.y - vecA.y) - (this.y - vecA.y) * (vecB.x - vecA.x);\r\n }\r\n\r\n /**\r\n * Checks whether or not this vector is on the same side of a line spanned by two vectors as another vector.\r\n *\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @param {Vector2} vecC A vector to check whether or not it is on the same side as this vector.\r\n * @returns {Boolean} Returns a boolean indicating whether or not this vector is on the same side as another vector.\r\n */\r\n sameSideAs(vecA, vecB, vecC) {\r\n let d = this.whichSide(vecA, vecB);\r\n let dRef = vecC.whichSide(vecA, vecB);\r\n\r\n return d < 0 && dRef < 0 || d == 0 && dRef == 0 || d > 0 && dRef > 0;\r\n }\r\n\r\n /**\r\n * Adds two vectors and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A summand.\r\n * @param {Vector2} vecB A summand.\r\n * @returns {Vector2} Returns the sum of two vectors.\r\n */\r\n static add(vecA, vecB) {\r\n return new Vector2(vecA.x + vecB.x, vecA.y + vecB.y);\r\n }\r\n\r\n /**\r\n * Subtracts one vector from another and returns the result as a new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The minuend.\r\n * @param {Vector2} vecB The subtrahend.\r\n * @returns {Vector2} Returns the difference of two vectors.\r\n */\r\n static subtract(vecA, vecB) {\r\n return new Vector2(vecA.x - vecB.x, vecA.y - vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiply(vecA, vecB) {\r\n return new Vector2(vecA.x * vecB.x, vecA.y * vecB.y);\r\n }\r\n\r\n /**\r\n * Multiplies two vectors (value by value) and returns the result.\r\n *\r\n * @static\r\n * @param {Vector2} vec A vector.\r\n * @param {Number} scalar A scalar.\r\n * @returns {Vector2} Returns the product of two vectors.\r\n */\r\n static multiplyScalar(vec, scalar) {\r\n return new Vector2(vec.x, vec.y).multiplyScalar(scalar);\r\n }\r\n\r\n /**\r\n * Returns the midpoint of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2} The midpoint of the line spanned by two vectors.\r\n */\r\n static midpoint(vecA, vecB) {\r\n return new Vector2((vecA.x + vecB.x) / 2, (vecA.y + vecB.y) / 2);\r\n }\r\n\r\n /**\r\n * Returns the normals of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two normals, each represented by a vector.\r\n */\r\n static normals(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n new Vector2(-delta.y, delta.x),\r\n new Vector2(delta.y, -delta.x)\r\n ];\r\n }\r\n\r\n /**\r\n * Returns the unit (normalized normal) vectors of a line spanned by two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector spanning the line.\r\n * @param {Vector2} vecB A vector spanning the line.\r\n * @returns {Vector2[]} An array containing the two unit vectors.\r\n */\r\n static units(vecA, vecB) {\r\n let delta = Vector2.subtract(vecB, vecA);\r\n\r\n return [\r\n (new Vector2(-delta.y, delta.x)).normalize(),\r\n (new Vector2(delta.y, -delta.x)).normalize()\r\n ];\r\n }\r\n\r\n /**\r\n * Divides a vector by another vector and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Vector2} vecB The divisor.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divide(vecA, vecB) {\r\n return new Vector2(vecA.x / vecB.x, vecA.y / vecB.y);\r\n }\r\n\r\n /**\r\n * Divides a vector by a scalar and returns the result as new vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The dividend.\r\n * @param {Number} s The scalar.\r\n * @returns {Vector2} The fraction of the two vectors.\r\n */\r\n static divideScalar(vecA, s) {\r\n return new Vector2(vecA.x / s, vecA.y / s);\r\n }\r\n\r\n /**\r\n * Returns the dot product of two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The dot product of two vectors.\r\n */\r\n static dot(vecA, vecB) {\r\n return vecA.x * vecB.x + vecA.y * vecB.y;\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A vector.\r\n * @returns {Number} The angle between two vectors in radians.\r\n */\r\n static angle(vecA, vecB) {\r\n let dot = Vector2.dot(vecA, vecB);\r\n\r\n return Math.acos(dot / (vecA.length() * vecB.length()));\r\n }\r\n\r\n /**\r\n * Returns the angle between two vectors based on a third vector in between.\r\n *\r\n * @static\r\n * @param {Vector2} vecA A vector.\r\n * @param {Vector2} vecB A (central) vector.\r\n * @param {Vector2} vecC A vector.\r\n * @returns {Number} The angle in radians.\r\n */\r\n static threePointangle(vecA, vecB, vecC) {\r\n let ab = Vector2.subtract(vecB, vecA);\r\n let bc = Vector2.subtract(vecC, vecB);\r\n let abLength = vecA.distance(vecB);\r\n let bcLength = vecB.distance(vecC);\r\n\r\n return Math.acos(Vector2.dot(ab, bc) / (abLength * bcLength));\r\n }\r\n \r\n /**\r\n * Returns the scalar projection of a vector on another vector.\r\n *\r\n * @static\r\n * @param {Vector2} vecA The vector to be projected.\r\n * @param {Vector2} vecB The vector to be projection upon.\r\n * @returns {Number} The scalar component.\r\n */\r\n static scalarProjection(vecA, vecB) {\r\n let unit = vecB.normalized();\r\n \r\n return Vector2.dot(vecA, unit);\r\n }\r\n\r\n /**\r\n * Returns the average vector (normalized) of the input vectors.\r\n *\r\n * @static\r\n * @param {Array} vecs An array containing vectors.\r\n * @returns {Vector2} The resulting vector (normalized).\r\n */\r\n static averageDirection(vecs) {\r\n let avg = new Vector2(0.0, 0.0);\r\n\r\n for (var i = 0; i < vecs.length; i++) {\r\n let vec = vecs[i];\r\n avg.add(vec);\r\n }\r\n\r\n return avg.normalize();\r\n }\r\n}\r\n\r\nmodule.exports = Vector2;","//@ts-check\r\nconst MathHelper = require('./MathHelper')\r\nconst ArrayHelper = require('./ArrayHelper')\r\nconst Vector2 = require('./Vector2')\r\nconst Atom = require('./Atom')\r\nconst VertexState = require('./VertexState')\r\n\r\n/** \r\n * A class representing a vertex.\r\n * \r\n * @property {Number} id The id of this vertex.\r\n * @property {Atom} value The atom associated with this vertex.\r\n * @property {Vector2} position The position of this vertex.\r\n * @property {Vector2} previousPosition The position of the previous vertex.\r\n * @property {Number|null} parentVertexId The id of the previous vertex.\r\n * @property {Number[]} children The ids of the children of this vertex.\r\n * @property {Number[]} spanningTreeChildren The ids of the children of this vertex as defined in the spanning tree defined by the SMILES.\r\n * @property {Number[]} edges The ids of edges associated with this vertex.\r\n * @property {Boolean} positioned A boolean indicating whether or not this vertex has been positioned.\r\n * @property {Number} angle The angle of this vertex.\r\n * @property {Number} dir The direction of this vertex.\r\n * @property {Number} neighbourCount The number of neighbouring vertices.\r\n * @property {Number[]} neighbours The vertex ids of neighbouring vertices.\r\n * @property {String[]} neighbouringElements The element symbols associated with neighbouring vertices.\r\n * @property {Boolean} forcePositioned A boolean indicating whether or not this vertex was positioned using a force-based approach.\r\n * @property {Number} vertexState enum of VertexState for DFS.\r\n */\r\n\r\nclass Vertex {\r\n /**\r\n * The constructor for the class Vertex.\r\n *\r\n * @param {Atom} value The value associated with this vertex.\r\n * @param {Number} [x=0] The initial x coordinate of the positional vector of this vertex.\r\n * @param {Number} [y=0] The initial y coordinate of the positional vector of this vertex.\r\n */\r\n constructor(value, x = 0, y = 0) {\r\n this.id = null;\r\n this.value = value;\r\n this.position = new Vector2(x ? x : 0, y ? y : 0);\r\n this.previousPosition = new Vector2(0, 0);\r\n this.parentVertexId = null;\r\n this.children = Array();\r\n this.spanningTreeChildren = Array();\r\n this.edges = Array();\r\n this.positioned = false;\r\n this.angle = null;\r\n this.dir = 1.0;\r\n this.neighbourCount = 0;\r\n this.neighbours = Array();\r\n this.neighbouringElements = Array();\r\n this.forcePositioned = false;\r\n this.vertexState = VertexState.VALUES.NOT_FOUND;\r\n this.component = -1;\r\n this.digits = [];\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex.\r\n * \r\n * @param {Number} x The x component of the coordinates.\r\n * @param {Number} y The y component of the coordinates.\r\n * \r\n */\r\n setPosition(x, y) {\r\n this.position.x = x;\r\n this.position.y = y;\r\n }\r\n\r\n /**\r\n * Set the 2D coordinates of the vertex from a Vector2.\r\n * \r\n * @param {Vector2} v A 2D vector.\r\n * \r\n */\r\n setPositionFromVector(v) {\r\n this.position.x = v.x;\r\n this.position.y = v.y;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n */\r\n addChild(vertexId) {\r\n this.children.push(vertexId);\r\n this.neighbours.push(vertexId);\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Add a child vertex id to this vertex as the second child of the neighbours array,\r\n * except this vertex is the first vertex of the SMILE string, then it is added as the first.\r\n * This is used to get the correct ordering of neighbours for parity calculations.\r\n * If a hydrogen is implicitly attached to the chiral center, insert as the third child.\r\n * @param {Number} vertexId The id of a vertex to be added as a child to this vertex.\r\n * @param {Number} ringbondIndex The index of the ringbond.\r\n */\r\n addRingbondChild(vertexId, ringbondIndex) {\r\n this.children.push(vertexId);\r\n\r\n if (this.value.bracket) {\r\n let index = 1;\r\n\r\n if (this.id === 0 && this.value.bracket.hcount === 0) {\r\n index = 0;\r\n }\r\n \r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 0) {\r\n index = 2;\r\n }\r\n\r\n if (this.value.bracket.hcount === 1 && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 2;\r\n } else {\r\n index = 3;\r\n }\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 0) {\r\n index = 1;\r\n }\r\n\r\n if (this.value.bracket.hcount === null && ringbondIndex === 1) {\r\n if (this.neighbours.length < 3) {\r\n index = 1;\r\n } else {\r\n index = 2;\r\n }\r\n }\r\n \r\n this.neighbours.splice(index, 0, vertexId);\r\n } else {\r\n this.neighbours.push(vertexId);\r\n }\r\n\r\n this.neighbourCount++;\r\n }\r\n\r\n /**\r\n * Set the vertex id of the parent.\r\n * \r\n * @param {Number} parentVertexId The parents vertex id.\r\n */\r\n setParentVertexId(parentVertexId) {\r\n this.neighbourCount++;\r\n this.parentVertexId = parentVertexId;\r\n this.neighbours.push(parentVertexId);\r\n }\r\n\r\n /**\r\n * Returns true if this vertex is terminal (has no parent or child vertices), otherwise returns false. Always returns true if associated value has property hasAttachedPseudoElements set to true.\r\n *\r\n * @returns {Boolean} A boolean indicating whether or not this vertex is terminal.\r\n */\r\n isTerminal() {\r\n if (this.value.hasAttachedPseudoElements) {\r\n return true;\r\n }\r\n\r\n return (this.parentVertexId === null && this.children.length < 2) || this.children.length === 0;\r\n }\r\n\r\n /**\r\n * Clones this vertex and returns the clone.\r\n *\r\n * @returns {Vertex} A clone of this vertex.\r\n */\r\n clone() {\r\n let clone = new Vertex(this.value, this.position.x, this.position.y);\r\n clone.id = this.id;\r\n clone.previousPosition = new Vector2(this.previousPosition.x, this.previousPosition.y);\r\n clone.parentVertexId = this.parentVertexId;\r\n clone.children = ArrayHelper.clone(this.children);\r\n clone.spanningTreeChildren = ArrayHelper.clone(this.spanningTreeChildren);\r\n clone.edges = ArrayHelper.clone(this.edges);\r\n clone.positioned = this.positioned;\r\n clone.angle = this.angle;\r\n clone.forcePositioned = this.forcePositioned;\r\n return clone;\r\n }\r\n\r\n /**\r\n * Returns true if this vertex and the supplied vertex both have the same id, else returns false.\r\n *\r\n * @param {Vertex} vertex The vertex to check.\r\n * @returns {Boolean} A boolean indicating whether or not the two vertices have the same id.\r\n */\r\n equals(vertex) {\r\n return this.id === vertex.id;\r\n }\r\n\r\n /**\r\n * Returns the angle of this vertexes positional vector. If a reference vector is supplied in relations to this vector, else in relations to the coordinate system.\r\n *\r\n * @param {Vector2} [referenceVector=null] - The reference vector.\r\n * @param {Boolean} [returnAsDegrees=false] - If true, returns angle in degrees, else in radians.\r\n * @returns {Number} The angle of this vertex.\r\n */\r\n getAngle(referenceVector = null, returnAsDegrees = false) {\r\n let u = null;\r\n\r\n if (!referenceVector) {\r\n u = Vector2.subtract(this.position, this.previousPosition);\r\n } else {\r\n u = Vector2.subtract(this.position, referenceVector);\r\n }\r\n\r\n if (returnAsDegrees) {\r\n return MathHelper.toDeg(u.angle());\r\n }\r\n\r\n return u.angle();\r\n }\r\n\r\n /**\r\n * Returns the suggested text direction when text is added at the position of this vertex.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @returns {String} The suggested direction of the text.\r\n */\r\n getTextDirection(vertices) {\r\n let neighbours = this.getDrawnNeighbours(vertices);\r\n let angles = Array();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n angles.push(this.getAngle(vertices[neighbours[i]].position));\r\n }\r\n\r\n let textAngle = MathHelper.meanAngle(angles);\r\n\r\n // Round to 0, 90, 180 or 270 degree\r\n let halfPi = Math.PI / 2.0;\r\n textAngle = Math.round(Math.round(textAngle / halfPi) * halfPi);\r\n\r\n if (textAngle === 2) {\r\n return 'down';\r\n } else if (textAngle === -2) {\r\n return 'up';\r\n } else if (textAngle === 0 || textAngle === -0) {\r\n return 'right'; // is checking for -0 necessary?\r\n } else if (textAngle === 3 || textAngle === -3) {\r\n return 'left';\r\n } else {\r\n return 'down'; // default to down\r\n }\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices.\r\n *\r\n * @param {Number} [vertexId=null] If a value is supplied, the vertex with this id is excluded from the returned indices.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices.\r\n */\r\n getNeighbours(vertexId = null) {\r\n if (vertexId === null) {\r\n return this.neighbours.slice();\r\n }\r\n\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (this.neighbours[i] !== vertexId) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns an array of ids of neighbouring vertices that will be drawn (vertex.value.isDrawn === true).\r\n * \r\n * @param {Vertex[]} vertices An array containing the vertices associated with the current molecule.\r\n * @returns {Number[]} An array containing the ids of neighbouring vertices that will be drawn.\r\n */\r\n getDrawnNeighbours(vertices) {\r\n let arr = Array();\r\n\r\n for (let i = 0; i < this.neighbours.length; i++) {\r\n if (vertices[this.neighbours[i]].value.isDrawn) {\r\n arr.push(this.neighbours[i]);\r\n }\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n /**\r\n * Returns the number of neighbours of this vertex.\r\n *\r\n * @returns {Number} The number of neighbours.\r\n */\r\n getNeighbourCount() {\r\n return this.neighbourCount;\r\n }\r\n\r\n /**\r\n * Returns a list of ids of vertices neighbouring this one in the original spanning tree, excluding the ringbond connections.\r\n *\r\n * @param {Number} [vertexId=null] If supplied, the vertex with this id is excluded from the array returned.\r\n * @returns {Number[]} An array containing the ids of the neighbouring vertices.\r\n */\r\n getSpanningTreeNeighbours(vertexId = null) {\r\n let neighbours = Array();\r\n\r\n for (let i = 0; i < this.spanningTreeChildren.length; i++) {\r\n if (vertexId === undefined || vertexId != this.spanningTreeChildren[i]) {\r\n neighbours.push(this.spanningTreeChildren[i]);\r\n }\r\n }\r\n\r\n if (this.parentVertexId != null) {\r\n if (vertexId === undefined || vertexId != this.parentVertexId) {\r\n neighbours.push(this.parentVertexId);\r\n }\r\n }\r\n\r\n return neighbours;\r\n }\r\n\r\n /**\r\n * Gets the next vertex in the ring in opposide direction to the supplied vertex id.\r\n *\r\n * @param {Vertex[]} vertices The array of vertices for the current molecule.\r\n * @param {Number} ringId The id of the ring containing this vertex.\r\n * @param {Number} previousVertexId The id of the previous vertex. The next vertex will be opposite from the vertex with this id as seen from this vertex.\r\n * @returns {Number} The id of the next vertex in the ring.\r\n */\r\n getNextInRing(vertices, ringId, previousVertexId) {\r\n let neighbours = this.getNeighbours();\r\n\r\n for (let i = 0; i < neighbours.length; i++) {\r\n if (ArrayHelper.contains(vertices[neighbours[i]].value.rings, {\r\n value: ringId\r\n }) &&\r\n neighbours[i] != previousVertexId) {\r\n return neighbours[i];\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n\r\nmodule.exports = Vertex;","//@ts-check\r\n\r\nclass VertexState {\r\n\r\n /**\r\n * Enum values of Vertex State for DFS\r\n * @return {{NOT_FOUND: number, OPEN: number, CLOSED: number, FULLY_CLOSED: number}}\r\n */\r\n static get VALUES() {\r\n return { NOT_FOUND: 0, OPEN: 1, CLOSED: 2, FULLY_CLOSED: 3 };\r\n }\r\n}\r\n\r\nmodule.exports = VertexState;\r\n"]} \ No newline at end of file diff --git a/doc/ArrayHelper.html b/doc/ArrayHelper.html index efb937dd..f1df5476 100644 --- a/doc/ArrayHelper.html +++ b/doc/ArrayHelper.html @@ -3398,7 +3398,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/ArrayHelper.js.html b/doc/ArrayHelper.js.html index 71316b49..93385a5d 100644 --- a/doc/ArrayHelper.js.html +++ b/doc/ArrayHelper.js.html @@ -438,7 +438,7 @@

ArrayHelper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Atom.html b/doc/Atom.html index 5556db12..dc454538 100644 --- a/doc/Atom.html +++ b/doc/Atom.html @@ -2906,7 +2906,7 @@

restoreRi
- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Atom.js.html b/doc/Atom.js.html index 703d86e0..69436f89 100644 --- a/doc/Atom.js.html +++ b/doc/Atom.js.html @@ -594,7 +594,7 @@

Atom.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/CanvasWrapper.html b/doc/CanvasWrapper.html index 4f05fc9e..b285161c 100644 --- a/doc/CanvasWrapper.html +++ b/doc/CanvasWrapper.html @@ -3783,7 +3783,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/CanvasWrapper.js.html b/doc/CanvasWrapper.js.html index 156d90fc..c9c6a5bf 100644 --- a/doc/CanvasWrapper.js.html +++ b/doc/CanvasWrapper.js.html @@ -948,7 +948,7 @@

CanvasWrapper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/DecayPoint.js.html b/doc/DecayPoint.js.html index 464df510..08fe7c4e 100644 --- a/doc/DecayPoint.js.html +++ b/doc/DecayPoint.js.html @@ -73,7 +73,7 @@

DecayPoint.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Drawer.html b/doc/Drawer.html index 61ab8362..204affcf 100644 --- a/doc/Drawer.html +++ b/doc/Drawer.html @@ -10857,7 +10857,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Drawer.js.html b/doc/Drawer.js.html index de5c9462..1c4f9bb0 100644 --- a/doc/Drawer.js.html +++ b/doc/Drawer.js.html @@ -3218,7 +3218,7 @@

Drawer.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Edge.html b/doc/Edge.html index c9b360bb..546e7605 100644 --- a/doc/Edge.html +++ b/doc/Edge.html @@ -1113,7 +1113,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Edge.js.html b/doc/Edge.js.html index 1c38aae4..2fa144e9 100644 --- a/doc/Edge.js.html +++ b/doc/Edge.js.html @@ -134,7 +134,7 @@

Edge.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Graph.html b/doc/Graph.html index 7a181df0..e4f95de4 100644 --- a/doc/Graph.html +++ b/doc/Graph.html @@ -8816,7 +8816,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Graph.js.html b/doc/Graph.js.html index 297e56e0..45ac9d3e 100644 --- a/doc/Graph.js.html +++ b/doc/Graph.js.html @@ -1890,7 +1890,7 @@

Graph.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Line.html b/doc/Line.html index c983cb67..2ac750c1 100644 --- a/doc/Line.html +++ b/doc/Line.html @@ -3056,7 +3056,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Line.js.html b/doc/Line.js.html index 66fa79c3..fc68a983 100644 --- a/doc/Line.js.html +++ b/doc/Line.js.html @@ -358,7 +358,7 @@

Line.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MathHelper.html b/doc/MathHelper.html index e48b43aa..b8937c19 100644 --- a/doc/MathHelper.html +++ b/doc/MathHelper.html @@ -1869,7 +1869,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MathHelper.js.html b/doc/MathHelper.js.html index 2fc569ab..3070c449 100644 --- a/doc/MathHelper.js.html +++ b/doc/MathHelper.js.html @@ -214,7 +214,7 @@

MathHelper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableBoolean.html b/doc/MutableBoolean.html index 4a82b072..7392a187 100644 --- a/doc/MutableBoolean.html +++ b/doc/MutableBoolean.html @@ -275,7 +275,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableBoolean.js.html b/doc/MutableBoolean.js.html index c15cb158..04a1f89d 100644 --- a/doc/MutableBoolean.js.html +++ b/doc/MutableBoolean.js.html @@ -79,7 +79,7 @@

MutableBoolean.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableCounter.html b/doc/MutableCounter.html index 66fbc6f5..0ce8e782 100644 --- a/doc/MutableCounter.html +++ b/doc/MutableCounter.html @@ -223,7 +223,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/MutableCounter.js.html b/doc/MutableCounter.js.html index e371ded1..87b6095d 100644 --- a/doc/MutableCounter.js.html +++ b/doc/MutableCounter.js.html @@ -80,7 +80,7 @@

MutableCounter.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Ring.html b/doc/Ring.html index 49361e42..0cf423df 100644 --- a/doc/Ring.html +++ b/doc/Ring.html @@ -1908,7 +1908,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Ring.js.html b/doc/Ring.js.html index 3fae9f31..2c333f75 100644 --- a/doc/Ring.js.html +++ b/doc/Ring.js.html @@ -267,7 +267,7 @@

Ring.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/RingConnection.html b/doc/RingConnection.html index 2f723821..100632c8 100644 --- a/doc/RingConnection.html +++ b/doc/RingConnection.html @@ -1602,7 +1602,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/RingConnection.js.html b/doc/RingConnection.js.html index 49052597..23846c7e 100644 --- a/doc/RingConnection.js.html +++ b/doc/RingConnection.js.html @@ -216,7 +216,7 @@

RingConnection.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SSSR.html b/doc/SSSR.html index 66f7a9ae..2b7035da 100644 --- a/doc/SSSR.html +++ b/doc/SSSR.html @@ -2524,7 +2524,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:59 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SSSR.js.html b/doc/SSSR.js.html index 9b3e0477..fb52f87f 100644 --- a/doc/SSSR.js.html +++ b/doc/SSSR.js.html @@ -626,7 +626,7 @@

SSSR.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SvgDrawer.js.html b/doc/SvgDrawer.js.html index aa0165d3..b50246a4 100644 --- a/doc/SvgDrawer.js.html +++ b/doc/SvgDrawer.js.html @@ -394,7 +394,7 @@

SvgDrawer.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/SvgWrapper.js.html b/doc/SvgWrapper.js.html index 58306f86..e68f9ed0 100644 --- a/doc/SvgWrapper.js.html +++ b/doc/SvgWrapper.js.html @@ -659,7 +659,7 @@

SvgWrapper.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/ThemeManager.js.html b/doc/ThemeManager.js.html index 2b719bc9..7c2324c9 100644 --- a/doc/ThemeManager.js.html +++ b/doc/ThemeManager.js.html @@ -97,7 +97,7 @@

ThemeManager.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/UtilityFunctions.js.html b/doc/UtilityFunctions.js.html index 2a07c87b..52b40ce9 100644 --- a/doc/UtilityFunctions.js.html +++ b/doc/UtilityFunctions.js.html @@ -78,7 +78,7 @@

UtilityFunctions.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:49 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vector2.html b/doc/Vector2.html index 630d55d7..43d2ce49 100644 --- a/doc/Vector2.html +++ b/doc/Vector2.html @@ -7088,7 +7088,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:46:00 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vector2.js.html b/doc/Vector2.js.html index bc8e6d09..5be94bb7 100644 --- a/doc/Vector2.js.html +++ b/doc/Vector2.js.html @@ -684,7 +684,7 @@

Vector2.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vertex.html b/doc/Vertex.html index 7ecd7c76..8cdfcf8b 100644 --- a/doc/Vertex.html +++ b/doc/Vertex.html @@ -3036,7 +3036,7 @@
Parameters:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:46:00 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/Vertex.js.html b/doc/Vertex.js.html index 9478a075..e8c5d67d 100644 --- a/doc/Vertex.js.html +++ b/doc/Vertex.js.html @@ -403,7 +403,7 @@

Vertex.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/VertexState.js.html b/doc/VertexState.js.html index 69dec15e..ee5c4310 100644 --- a/doc/VertexState.js.html +++ b/doc/VertexState.js.html @@ -70,7 +70,7 @@

VertexState.js


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/global.html b/doc/global.html index 29fd9344..e6da5fba 100644 --- a/doc/global.html +++ b/doc/global.html @@ -297,7 +297,7 @@
Returns:

- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/doc/index.html b/doc/index.html index 6390560b..5526a9b3 100644 --- a/doc/index.html +++ b/doc/index.html @@ -381,7 +381,7 @@

Contributors


- Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:38:50 GMT+0200 (Středoevropský letní čas) using the docdash theme. + Documentation generated by JSDoc 3.6.5 on Fri Apr 23 2021 10:45:58 GMT+0200 (Středoevropský letní čas) using the docdash theme.
diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 41cebd4d..00000000 --- a/package-lock.json +++ /dev/null @@ -1,8406 +0,0 @@ -{ - "name": "smiles-drawer", - "version": "2.1.6", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/core": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", - "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.1", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.0", - "@babel/types": "^7.11.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", - "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - } - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/template": "^7.10.4", - "@babel/types": "^7.11.0", - "lodash": "^4.17.19" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/helpers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", - "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.11.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz", - "integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==", - "dev": true - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^7.11.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "@gulp-sourcemaps/identity-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", - "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", - "dev": true, - "requires": { - "acorn": "^6.4.1", - "normalize-path": "^3.0.0", - "postcss": "^7.0.16", - "source-map": "^0.6.0", - "through2": "^3.0.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "requires": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", - "dev": true - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "dev": true, - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - } - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-filter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", - "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", - "dev": true - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async-done": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", - "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^2.0.0", - "stream-exhaust": "^1.0.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - } - } - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "available-typed-arrays": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", - "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", - "dev": true, - "requires": { - "array-filter": "^1.0.0" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "babel-core": { - "version": "6.26.3", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", - "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-generator": "^6.26.0", - "babel-helpers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-register": "^6.26.0", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "convert-source-map": "^1.5.1", - "debug": "^2.6.9", - "json5": "^0.5.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.4", - "path-is-absolute": "^1.0.1", - "private": "^0.1.8", - "slash": "^1.0.0", - "source-map": "^0.5.7" - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } - } - }, - "babel-helper-evaluate-path": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", - "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", - "dev": true - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-flip-expressions": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", - "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", - "dev": true - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-is-nodes-equiv": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", - "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", - "dev": true - }, - "babel-helper-is-void-0": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", - "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", - "dev": true - }, - "babel-helper-mark-eval-scopes": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", - "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", - "dev": true - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-remove-or-void": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", - "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", - "dev": true - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-to-multiple-sequence-expressions": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", - "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", - "dev": true - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-minify-builtins": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", - "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", - "dev": true - }, - "babel-plugin-minify-constant-folding": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", - "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "babel-plugin-minify-dead-code-elimination": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz", - "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-mark-eval-scopes": "^0.4.3", - "babel-helper-remove-or-void": "^0.4.3", - "lodash": "^4.17.11" - } - }, - "babel-plugin-minify-flip-comparisons": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", - "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", - "dev": true, - "requires": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "babel-plugin-minify-guarded-expressions": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", - "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3" - } - }, - "babel-plugin-minify-infinity": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", - "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", - "dev": true - }, - "babel-plugin-minify-mangle-names": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", - "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", - "dev": true, - "requires": { - "babel-helper-mark-eval-scopes": "^0.4.3" - } - }, - "babel-plugin-minify-numeric-literals": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", - "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", - "dev": true - }, - "babel-plugin-minify-replace": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", - "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", - "dev": true - }, - "babel-plugin-minify-simplify": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", - "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3", - "babel-helper-is-nodes-equiv": "^0.0.1", - "babel-helper-to-multiple-sequence-expressions": "^0.5.0" - } - }, - "babel-plugin-minify-type-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", - "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", - "dev": true, - "requires": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", - "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", - "babel-plugin-syntax-exponentiation-operator": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-inline-consecutive-adds": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", - "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", - "dev": true - }, - "babel-plugin-transform-member-expression-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", - "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", - "dev": true - }, - "babel-plugin-transform-merge-sibling-variables": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", - "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", - "dev": true - }, - "babel-plugin-transform-minify-booleans": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", - "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", - "dev": true - }, - "babel-plugin-transform-property-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", - "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } - }, - "babel-plugin-transform-regexp-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", - "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", - "dev": true - }, - "babel-plugin-transform-remove-console": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", - "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", - "dev": true - }, - "babel-plugin-transform-remove-debugger": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", - "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", - "dev": true - }, - "babel-plugin-transform-remove-undefined": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", - "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "babel-plugin-transform-simplify-comparison-operators": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", - "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", - "dev": true - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-undefined-to-void": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", - "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", - "dev": true - }, - "babel-preset-env": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", - "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-syntax-trailing-function-commas": "^6.22.0", - "babel-plugin-transform-async-to-generator": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.23.0", - "babel-plugin-transform-es2015-classes": "^6.23.0", - "babel-plugin-transform-es2015-computed-properties": "^6.22.0", - "babel-plugin-transform-es2015-destructuring": "^6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", - "babel-plugin-transform-es2015-for-of": "^6.23.0", - "babel-plugin-transform-es2015-function-name": "^6.22.0", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.22.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", - "babel-plugin-transform-es2015-modules-umd": "^6.23.0", - "babel-plugin-transform-es2015-object-super": "^6.22.0", - "babel-plugin-transform-es2015-parameters": "^6.23.0", - "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", - "babel-plugin-transform-exponentiation-operator": "^6.22.0", - "babel-plugin-transform-regenerator": "^6.22.0", - "browserslist": "^3.2.6", - "invariant": "^2.2.2", - "semver": "^5.3.0" - } - }, - "babel-preset-minify": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", - "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==", - "dev": true, - "requires": { - "babel-plugin-minify-builtins": "^0.5.0", - "babel-plugin-minify-constant-folding": "^0.5.0", - "babel-plugin-minify-dead-code-elimination": "^0.5.1", - "babel-plugin-minify-flip-comparisons": "^0.4.3", - "babel-plugin-minify-guarded-expressions": "^0.4.4", - "babel-plugin-minify-infinity": "^0.4.3", - "babel-plugin-minify-mangle-names": "^0.5.0", - "babel-plugin-minify-numeric-literals": "^0.4.3", - "babel-plugin-minify-replace": "^0.5.0", - "babel-plugin-minify-simplify": "^0.5.1", - "babel-plugin-minify-type-constructors": "^0.4.3", - "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", - "babel-plugin-transform-member-expression-literals": "^6.9.4", - "babel-plugin-transform-merge-sibling-variables": "^6.9.4", - "babel-plugin-transform-minify-booleans": "^6.9.4", - "babel-plugin-transform-property-literals": "^6.9.4", - "babel-plugin-transform-regexp-constructors": "^0.4.3", - "babel-plugin-transform-remove-console": "^6.9.4", - "babel-plugin-transform-remove-debugger": "^6.9.4", - "babel-plugin-transform-remove-undefined": "^0.5.0", - "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", - "babel-plugin-transform-undefined-to-void": "^6.9.4", - "lodash": "^4.17.11" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "^6.26.0", - "babel-runtime": "^6.26.0", - "core-js": "^2.5.0", - "home-or-tmp": "^2.0.0", - "lodash": "^4.17.4", - "mkdirp": "^0.5.1", - "source-map-support": "^0.4.15" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babelify": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", - "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", - "dev": true - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "dev": true - }, - "beeper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-2.0.0.tgz", - "integrity": "sha512-+ShExQEewPvKdTUOtCAJmkUAgEyNF0QqgiAhPRE5xLvoFkIPt8xuHKaz1gMLzSMS73beHWs9gbRBngdH61nVWw==", - "dev": true, - "requires": { - "delay": "^4.1.0" - } - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", - "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-pack": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", - "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "combine-source-map": "~0.8.0", - "defined": "^1.0.0", - "safe-buffer": "^5.1.1", - "through2": "^2.0.0", - "umd": "^3.0.0" - } - }, - "browser-resolve": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", - "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", - "dev": true, - "requires": { - "resolve": "^1.17.0" - } - }, - "browserify": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", - "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.1", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^3.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.2.1", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "^1.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum-object": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^3.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.12.0", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "requires": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - } - } - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", - "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000844", - "electron-to-chromium": "^1.3.47" - } - }, - "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "cached-path-relative": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", - "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001114", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001114.tgz", - "integrity": "sha512-ml/zTsfNBM+T1+mjglWRPgVsu2L76GAaADKX5f4t0pbhttEp0WMawJsHDYlFkVZkoA+89uvBRrVrEE4oqenzXQ==", - "dev": true - }, - "catharsis": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", - "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", - "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^1.0.6", - "through2": "^2.0.1" - } - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "combine-source-map": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", - "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", - "dev": true, - "requires": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" - }, - "dependencies": { - "convert-source-map": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", - "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", - "dev": true - } - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true, - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } - }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", - "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "source-map": "^0.6.1", - "source-map-resolve": "^0.6.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-resolve": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", - "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0" - } - } - } - }, - "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "dash-ast": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", - "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "debug-fabulous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "dev": true, - "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "delay": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-4.4.0.tgz", - "integrity": "sha512-txgOrJu3OdtOfTiEOT2e76dJVfG/1dz2NZ4F0Pyt4UGZJryssMRp5vdM5wQoLwSOBNdrJv3F9PAhp/heqd7vrA==", - "dev": true - }, - "deps-sort": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", - "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "shasum-object": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - } - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, - "detective": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", - "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", - "dev": true, - "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - } - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "docdash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/docdash/-/docdash-1.2.0.tgz", - "integrity": "sha512-IYZbgYthPTspgqYeciRJNPhSwL51yer7HAwDXhF5p+H7mTDbPvY3PCk/QDjNxdPCpWkaJVFC4t7iCNB/t9E5Kw==", - "dev": true - }, - "dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true - }, - "domhandler": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", - "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1" - } - }, - "domutils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz", - "integrity": "sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==", - "dev": true, - "requires": { - "dom-serializer": "^0.2.1", - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0" - } - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "electron-to-chromium": { - "version": "1.3.533", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.533.tgz", - "integrity": "sha512-YqAL+NXOzjBnpY+dcOKDlZybJDCOzgsq4koW3fvyty/ldTmsb4QazZpOWmVvZ2m0t5jbBf7L0lIGU3BUipwG+A==", - "dev": true - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - } - } - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - } - }, - "entities": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true - }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - } - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dev": true, - "requires": { - "type": "^2.0.0" - }, - "dependencies": { - "type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", - "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fancy-log": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", - "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "parse-node-version": "^1.0.0", - "time-stamp": "^1.0.0" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", - "dev": true - }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, - "get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true - }, - "glob-watcher": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", - "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "normalize-path": "^3.0.0", - "object.defaults": "^1.1.0" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "gulp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", - "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", - "dev": true, - "requires": { - "glob-watcher": "^5.0.3", - "gulp-cli": "^2.2.0", - "undertaker": "^1.2.1", - "vinyl-fs": "^3.0.0" - } - }, - "gulp-babel-minify": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/gulp-babel-minify/-/gulp-babel-minify-0.5.1.tgz", - "integrity": "sha512-qrwtUEbB64nADUUyEciNHGPQ4jYQyDEgorV2NrY3wItISjAhvQ3L2DH/twGNh8rGsEXpCsqItry5RmdVrfCoMg==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "babel-preset-minify": "^0.5.1", - "plugin-error": "^1.0.1", - "through2": "^2.0.3", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, - "gulp-cli": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", - "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.4.0", - "isobject": "^3.0.1", - "liftoff": "^3.1.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.2.0", - "yargs": "^7.1.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - } - } - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - }, - "dependencies": { - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "liftoff": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", - "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^3.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "fined": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", - "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - } - }, - "flagged-respawn": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", - "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", - "dev": true - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - } - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - }, - "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - }, - "dependencies": { - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - } - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - }, - "dependencies": { - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - } - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - }, - "dependencies": { - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - } - } - }, - "v8flags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", - "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" - }, - "dependencies": { - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - } - } - } - }, - "gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - } - } - }, - "gulp-exit": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/gulp-exit/-/gulp-exit-0.0.2.tgz", - "integrity": "sha1-CCMTVIaDrQqwXUMNelYzMNTmE3A=", - "dev": true - }, - "gulp-jsdoc3": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-jsdoc3/-/gulp-jsdoc3-3.0.0.tgz", - "integrity": "sha512-rE2jAwCPA8XFi9g4V3Z3LPhZNjxuMTIYQVMjdqZAQpRfJITLVaUK3xfmiiNTMc7j+fT7pL8Q5yj7ZPRdwCJWNg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1", - "beeper": "^2.0.0", - "debug": "^4.1.1", - "fancy-log": "^1.3.3", - "ink-docstrap": "^1.3.2", - "jsdoc": "^3.6.3", - "map-stream": "0.0.7", - "tmp": "0.1.0" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "gulp-rename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", - "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", - "dev": true - }, - "gulp-sourcemaps": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz", - "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", - "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "^2.0.1", - "@gulp-sourcemaps/map-sources": "^1.0.0", - "acorn": "^6.4.1", - "convert-source-map": "^1.0.0", - "css": "^3.0.0", - "debug-fabulous": "^1.0.0", - "detect-newline": "^2.0.0", - "graceful-fs": "^4.0.0", - "source-map": "^0.6.0", - "strip-bom-string": "^1.0.0", - "through2": "^2.0.0" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "htmlescape": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", - "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", - "dev": true - }, - "htmlparser2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", - "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^3.0.0", - "domutils": "^2.0.0", - "entities": "^2.0.0" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", - "dev": true - }, - "ink-docstrap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/ink-docstrap/-/ink-docstrap-1.3.2.tgz", - "integrity": "sha512-STx5orGQU1gfrkoI/fMU7lX6CSP7LBGO10gXNgOZhwKhUqbtNjCkYSewJtNnLmWP1tAGN6oyEpG1HFPw5vpa5Q==", - "dev": true, - "requires": { - "moment": "^2.14.1", - "sanitize-html": "^1.13.0" - } - }, - "inline-source-map": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", - "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", - "dev": true, - "requires": { - "source-map": "~0.5.3" - } - }, - "insert-module-globals": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", - "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arguments": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", - "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", - "dev": true, - "requires": { - "call-bind": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-generator-function": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz", - "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typed-array": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", - "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.0-next.2", - "foreach": "^2.0.5", - "has-symbols": "^1.0.1" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "jasmine": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.1.tgz", - "integrity": "sha512-Jqp8P6ZWkTVFGmJwBK46p+kJNrZCdqkQ4GL+PGuBXZwK1fM4ST9BizkYgIwCFqYYqnTizAy6+XG2Ej5dFrej9Q==", - "dev": true, - "requires": { - "fast-glob": "^2.2.6", - "jasmine-core": "~3.6.0" - } - }, - "jasmine-core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", - "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js2xmlparser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", - "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", - "dev": true, - "requires": { - "xmlcreate": "^2.0.3" - } - }, - "jsdoc": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.5.tgz", - "integrity": "sha512-SbY+i9ONuxSK35cgVHaI8O9senTE4CDYAmGSDJ5l3+sfe62Ff4gy96osy6OW84t4K4A8iGnMrlRrsSItSNp3RQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.9.4", - "bluebird": "^3.7.2", - "catharsis": "^0.8.11", - "escape-string-regexp": "^2.0.0", - "js2xmlparser": "^4.0.1", - "klaw": "^3.0.0", - "markdown-it": "^10.0.0", - "markdown-it-anchor": "^5.2.7", - "marked": "^0.8.2", - "mkdirp": "^1.0.4", - "requizzle": "^0.2.3", - "strip-json-comments": "^3.1.0", - "taffydb": "2.6.2", - "underscore": "~1.10.2" - }, - "dependencies": { - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "klaw": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", - "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, - "labeled-stream-splicer": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", - "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "stream-splicer": "^2.0.0" - } - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "linkify-it": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", - "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", - "dev": true, - "requires": { - "uc.micro": "^1.0.1" - } - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true - }, - "lodash.clone": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", - "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", - "dev": true - }, - "lodash.memoize": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", - "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", - "dev": true - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", - "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "markdown-it": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", - "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "entities": "~2.0.0", - "linkify-it": "^2.0.0", - "mdurl": "^1.0.1", - "uc.micro": "^1.0.5" - } - }, - "markdown-it-anchor": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", - "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", - "dev": true - }, - "marked": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", - "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", - "dev": true - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", - "dev": true - }, - "memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - }, - "dependencies": { - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - } - } - }, - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "module-deps": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", - "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "browser-resolve": "^2.0.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - } - }, - "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", - "dev": true - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "outpipe": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz", - "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=", - "dev": true, - "requires": { - "shell-quote": "^1.4.2" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "parents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", - "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", - "dev": true, - "requires": { - "path-platform": "~0.11.15" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse-srcset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-platform": { - "version": "0.11.15", - "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", - "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "read-only-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", - "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "regenerate": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "requizzle": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", - "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "sanitize-html": { - "version": "1.27.3", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.3.tgz", - "integrity": "sha512-79tcPlgJ3fuK0/TtUCIBdPeQSvktTSTJP9O/dzrteaO98qw5UV6CATh3ZyPjUzv1LtNjHDlhbq9XOXiKf0zA1w==", - "dev": true, - "requires": { - "htmlparser2": "^4.1.0", - "lodash": "^4.17.15", - "parse-srcset": "^1.0.2", - "postcss": "^7.0.27" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shasum-object": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", - "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", - "dev": true, - "requires": { - "fast-safe-stringify": "^2.0.7" - } - }, - "shell-quote": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", - "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", - "dev": true - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", - "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "ssri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", - "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "dev": true, - "requires": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-http": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz", - "integrity": "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - } - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", - "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "subarg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", - "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", - "dev": true, - "requires": { - "minimist": "^1.1.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "syntax-error": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", - "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", - "dev": true, - "requires": { - "acorn-node": "^1.2.0" - } - }, - "taffydb": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", - "dev": true - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "dev": true, - "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "timers-browserify": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", - "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", - "dev": true, - "requires": { - "process": "~0.11.0" - } - }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "tmp": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", - "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", - "dev": true, - "requires": { - "rimraf": "^2.6.3" - } - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tty-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", - "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", - "dev": true - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uc.micro": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", - "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", - "dev": true - }, - "umd": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", - "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - } - } - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "undeclared-identifiers": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", - "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", - "dev": true, - "requires": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "underscore": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", - "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", - "dev": true - }, - "undertaker": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", - "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - } - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", - "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz", - "integrity": "sha1-lsGjR5uMU5JULGEgKQE7Wyf4i78=", - "dev": true, - "requires": { - "bl": "^1.2.1", - "through2": "^2.0.3" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-source-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-2.0.0.tgz", - "integrity": "sha1-84pa+53R6Ttl1VBGmsYYKsT1S44=", - "dev": true, - "requires": { - "through2": "^2.0.3", - "vinyl": "^2.1.0" - }, - "dependencies": { - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "vinyl": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", - "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - } - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "watchify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz", - "integrity": "sha512-2Z04dxwoOeNxa11qzWumBTgSAohTC0+ScuY7XMenPnH+W2lhTcpEOJP4g2EIG/SWeLadPk47x++Yh+8BqPM/lA==", - "dev": true, - "requires": { - "anymatch": "^3.1.0", - "browserify": "^17.0.0", - "chokidar": "^3.4.0", - "defined": "^1.0.0", - "outpipe": "^1.1.0", - "through2": "^4.0.2", - "xtend": "^4.0.2" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserify": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", - "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", - "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.1", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^3.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.2.1", - "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "^1.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum-object": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^3.0.0", - "stream-http": "^3.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.12.0", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "insert-module-globals": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", - "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", - "dev": true, - "requires": { - "JSONStream": "^1.0.3", - "acorn-node": "^1.5.2", - "combine-source-map": "^0.8.0", - "concat-stream": "^1.6.1", - "is-buffer": "^1.1.0", - "path-is-absolute": "^1.0.1", - "process": "~0.11.0", - "through2": "^2.0.0", - "undeclared-identifiers": "^1.1.2", - "xtend": "^4.0.0" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "requires": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "util": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", - "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - } - } - }, - "watchpack": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", - "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", - "dev": true, - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.1" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "optional": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "optional": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "optional": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "optional": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "optional": true - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "optional": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "optional": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "watchpack-chokidar2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", - "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", - "dev": true, - "optional": true, - "requires": { - "chokidar": "^2.1.8" - } - }, - "webpack": { - "version": "4.46.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", - "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.5.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "dependencies": { - "acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "dev": true - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - } - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "webpack-stream": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-6.1.2.tgz", - "integrity": "sha512-Bpbsrix1cmWRN705JEg69ErgNAEOpQBvtuWKFW3ZCrLddoPPK6oVpQn4svxNdfedqMLlWA3GLOLvw4c7u63GqA==", - "dev": true, - "requires": { - "fancy-log": "^1.3.3", - "lodash.clone": "^4.3.2", - "lodash.some": "^4.2.2", - "memory-fs": "^0.5.0", - "plugin-error": "^1.0.1", - "supports-color": "^7.2.0", - "through": "^2.3.8", - "vinyl": "^2.1.0", - "webpack": "^4.26.1" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-typed-array": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", - "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.2", - "call-bind": "^1.0.0", - "es-abstract": "^1.18.0-next.1", - "foreach": "^2.0.5", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.1", - "is-typed-array": "^1.1.3" - } - }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xmlcreate": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", - "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - } - } -} From 5e0e062f755c6228a067ac3099c072b562f84073 Mon Sep 17 00:00:00 2001 From: privrja Date: Fri, 23 Apr 2021 10:46:55 +0200 Subject: [PATCH 6/6] Cyclic of 2 blocks --- package-lock.json | 18023 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 18023 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..dd845022 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,18023 @@ +{ + "name": "smiles-drawer", + "version": "2.1.6", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "smiles-drawer", + "version": "2.1.6", + "license": "MIT", + "devDependencies": { + "babel-core": ">=6.26.3", + "babel-preset-env": ">=1.7.0", + "babelify": "^10.0.0", + "browserify": ">=16.2.3", + "docdash": "^1.0.3", + "gulp": "^4.0.0", + "gulp-babel-minify": "^0.5.0", + "gulp-concat": ">=2.6.1", + "gulp-exit": "0.0.2", + "gulp-jsdoc3": ">=2.0.0", + "gulp-rename": ">=1.4.0", + "gulp-sourcemaps": "^3.0.0", + "jasmine": "^3.3.0", + "vinyl-buffer": ">=1.0.1", + "vinyl-source-stream": ">=2.0.0", + "watchify": "^4.0.0", + "webpack-stream": "^6.1.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/@babel/core": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", + "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.1", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@babel/core/node_modules/json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/generator": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", + "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.11.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "node_modules/@babel/generator/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.11.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.11.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "node_modules/@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.11.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz", + "integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "node_modules/@babel/traverse": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "node_modules/@babel/types/node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@gulp-sourcemaps/identity-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", + "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", + "dev": true, + "dependencies": { + "acorn": "^6.4.1", + "normalize-path": "^3.0.0", + "postcss": "^7.0.16", + "source-map": "^0.6.0", + "through2": "^3.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@gulp-sourcemaps/identity-map/node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "node_modules/@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "dependencies": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@gulp-sourcemaps/map-sources/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "dependencies": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "dependencies": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "node_modules/ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "dependencies": { + "ansi-wrap": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, + "node_modules/array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "dependencies": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "dependencies": { + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "dependencies": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/async-done/node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "dev": true, + "dependencies": { + "array-filter": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "dependencies": { + "esutils": "^2.0.2", + "chalk": "^1.1.3", + "js-tokens": "^3.0.2" + } + }, + "node_modules/babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "node_modules/babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "dependencies": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "node_modules/babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "dependencies": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "dependencies": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-helper-define-map/node_modules/lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "node_modules/babel-helper-evaluate-path": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", + "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", + "dev": true + }, + "node_modules/babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-flip-expressions": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", + "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", + "dev": true + }, + "node_modules/babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "dependencies": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-is-nodes-equiv": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", + "dev": true + }, + "node_modules/babel-helper-is-void-0": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", + "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", + "dev": true + }, + "node_modules/babel-helper-mark-eval-scopes": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", + "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", + "dev": true + }, + "node_modules/babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-helper-regex/node_modules/lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "node_modules/babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-remove-or-void": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", + "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", + "dev": true + }, + "node_modules/babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "dependencies": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-helper-to-multiple-sequence-expressions": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", + "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", + "dev": true + }, + "node_modules/babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-minify-builtins": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", + "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", + "dev": true + }, + "node_modules/babel-plugin-minify-constant-folding": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", + "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", + "dev": true, + "dependencies": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "node_modules/babel-plugin-minify-dead-code-elimination": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz", + "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==", + "dev": true, + "dependencies": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-mark-eval-scopes": "^0.4.3", + "babel-helper-remove-or-void": "^0.4.3", + "lodash": "^4.17.11" + } + }, + "node_modules/babel-plugin-minify-flip-comparisons": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", + "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", + "dev": true, + "dependencies": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "node_modules/babel-plugin-minify-guarded-expressions": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", + "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", + "dev": true, + "dependencies": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3" + } + }, + "node_modules/babel-plugin-minify-infinity": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", + "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", + "dev": true + }, + "node_modules/babel-plugin-minify-mangle-names": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", + "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", + "dev": true, + "dependencies": { + "babel-helper-mark-eval-scopes": "^0.4.3" + } + }, + "node_modules/babel-plugin-minify-numeric-literals": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", + "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", + "dev": true + }, + "node_modules/babel-plugin-minify-replace": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", + "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", + "dev": true + }, + "node_modules/babel-plugin-minify-simplify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", + "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", + "dev": true, + "dependencies": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3", + "babel-helper-is-nodes-equiv": "^0.0.1", + "babel-helper-to-multiple-sequence-expressions": "^0.5.0" + } + }, + "node_modules/babel-plugin-minify-type-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", + "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", + "dev": true, + "dependencies": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "node_modules/babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "node_modules/babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "node_modules/babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "node_modules/babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "dependencies": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-plugin-transform-es2015-block-scoping/node_modules/lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "node_modules/babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "dependencies": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "dependencies": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "dependencies": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "dependencies": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "node_modules/babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "dependencies": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "dependencies": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "dependencies": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "dependencies": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "dependencies": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "dependencies": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "node_modules/babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "dependencies": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-transform-inline-consecutive-adds": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", + "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", + "dev": true + }, + "node_modules/babel-plugin-transform-member-expression-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", + "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", + "dev": true + }, + "node_modules/babel-plugin-transform-merge-sibling-variables": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", + "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", + "dev": true + }, + "node_modules/babel-plugin-transform-minify-booleans": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", + "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", + "dev": true + }, + "node_modules/babel-plugin-transform-property-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", + "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + } + }, + "node_modules/babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.10.0" + } + }, + "node_modules/babel-plugin-transform-regexp-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", + "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", + "dev": true + }, + "node_modules/babel-plugin-transform-remove-console": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", + "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", + "dev": true + }, + "node_modules/babel-plugin-transform-remove-debugger": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", + "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", + "dev": true + }, + "node_modules/babel-plugin-transform-remove-undefined": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", + "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", + "dev": true, + "dependencies": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "node_modules/babel-plugin-transform-simplify-comparison-operators": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", + "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", + "dev": true + }, + "node_modules/babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "node_modules/babel-plugin-transform-undefined-to-void": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", + "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", + "dev": true + }, + "node_modules/babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "dependencies": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } + }, + "node_modules/babel-preset-minify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", + "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==", + "dev": true, + "dependencies": { + "babel-plugin-minify-builtins": "^0.5.0", + "babel-plugin-minify-constant-folding": "^0.5.0", + "babel-plugin-minify-dead-code-elimination": "^0.5.1", + "babel-plugin-minify-flip-comparisons": "^0.4.3", + "babel-plugin-minify-guarded-expressions": "^0.4.4", + "babel-plugin-minify-infinity": "^0.4.3", + "babel-plugin-minify-mangle-names": "^0.5.0", + "babel-plugin-minify-numeric-literals": "^0.4.3", + "babel-plugin-minify-replace": "^0.5.0", + "babel-plugin-minify-simplify": "^0.5.1", + "babel-plugin-minify-type-constructors": "^0.4.3", + "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", + "babel-plugin-transform-member-expression-literals": "^6.9.4", + "babel-plugin-transform-merge-sibling-variables": "^6.9.4", + "babel-plugin-transform-minify-booleans": "^6.9.4", + "babel-plugin-transform-property-literals": "^6.9.4", + "babel-plugin-transform-regexp-constructors": "^0.4.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "babel-plugin-transform-remove-debugger": "^6.9.4", + "babel-plugin-transform-remove-undefined": "^0.5.0", + "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", + "babel-plugin-transform-undefined-to-void": "^6.9.4", + "lodash": "^4.17.11" + } + }, + "node_modules/babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "dependencies": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/babelify": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", + "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true, + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "node_modules/beeper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-2.0.0.tgz", + "integrity": "sha512-+ShExQEewPvKdTUOtCAJmkUAgEyNF0QqgiAhPRE5xLvoFkIPt8xuHKaz1gMLzSMS73beHWs9gbRBngdH61nVWw==", + "dev": true, + "dependencies": { + "delay": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "dependencies": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + }, + "bin": { + "browser-pack": "bin/cmd.js" + } + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "dependencies": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-des/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-rsa/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserify/node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/browserify/node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/browserify/node_modules/stream-browserify/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/browserify/node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + }, + "bin": { + "browserslist": "cli.js" + } + }, + "node_modules/buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "chownr": "^1.1.1", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/cacache/node_modules/y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cached-path-relative": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", + "dev": true + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001114", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001114.tgz", + "integrity": "sha512-ml/zTsfNBM+T1+mjglWRPgVsu2L76GAaADKX5f4t0pbhttEp0WMawJsHDYlFkVZkoA+89uvBRrVrEE4oqenzXQ==", + "dev": true + }, + "node_modules/catharsis": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "node_modules/cloneable-readable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^1.0.6", + "through2": "^2.0.1" + } + }, + "node_modules/collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "dependencies": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "dependencies": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "node_modules/combine-source-map/node_modules/convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/concat-with-sourcemaps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "dependencies": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, + "node_modules/core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + } + }, + "node_modules/css/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css/node_modules/source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + }, + "node_modules/cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, + "dependencies": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + } + }, + "node_modules/debug-fabulous/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/debug-fabulous/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "dependencies": { + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-compare/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-property/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/delay": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-4.4.0.tgz", + "integrity": "sha512-txgOrJu3OdtOfTiEOT2e76dJVfG/1dz2NZ4F0Pyt4UGZJryssMRp5vdM5wQoLwSOBNdrJv3F9PAhp/heqd7vrA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "dev": true, + "dependencies": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + }, + "bin": { + "deps-sort": "bin/cmd.js" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "dependencies": { + "repeating": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "dependencies": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/docdash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/docdash/-/docdash-1.2.0.tgz", + "integrity": "sha512-IYZbgYthPTspgqYeciRJNPhSwL51yer7HAwDXhF5p+H7mTDbPvY3PCk/QDjNxdPCpWkaJVFC4t7iCNB/t9E5Kw==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "node_modules/domhandler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", + "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/domutils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz", + "integrity": "sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==", + "dev": true, + "dependencies": { + "dom-serializer": "^0.2.1", + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.3.533", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.533.tgz", + "integrity": "sha512-YqAL+NXOzjBnpY+dcOKDlZybJDCOzgsq4koW3fvyty/ldTmsb4QazZpOWmVvZ2m0t5jbBf7L0lIGU3BUipwG+A==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/elliptic/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-abstract/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-abstract/node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "dependencies": { + "type": "^2.0.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "dependencies": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/findup-sync/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-babel-minify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/gulp-babel-minify/-/gulp-babel-minify-0.5.1.tgz", + "integrity": "sha512-qrwtUEbB64nADUUyEciNHGPQ4jYQyDEgorV2NrY3wItISjAhvQ3L2DH/twGNh8rGsEXpCsqItry5RmdVrfCoMg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.1.0", + "babel-preset-minify": "^0.5.1", + "plugin-error": "^1.0.1", + "through2": "^2.0.3", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "node_modules/gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/gulp-cli/node_modules/cliui/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/gulp-cli/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/findup-sync/node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/findup-sync/node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "node_modules/gulp-cli/node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/gulp-cli/node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/gulp-cli/node_modules/liftoff/node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/gulp-cli/node_modules/liftoff/node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/liftoff/node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/liftoff/node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/liftoff/node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/load-json-file/node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/os-locale/node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/path-type/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/gulp-cli/node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/gulp-cli/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/gulp-cli/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/gulp-cli/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/string-width/node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/strip-bom/node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/gulp-cli/node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "node_modules/gulp-cli/node_modules/yargs": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + } + }, + "node_modules/gulp-cli/node_modules/yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + }, + "node_modules/gulp-cli/node_modules/yargs/node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/yargs/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/gulp-cli/node_modules/yargs/node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/yargs/node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "node_modules/gulp-cli/node_modules/yargs/node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "dependencies": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-concat/node_modules/clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/gulp-concat/node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "node_modules/gulp-concat/node_modules/replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-concat/node_modules/vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-exit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/gulp-exit/-/gulp-exit-0.0.2.tgz", + "integrity": "sha1-CCMTVIaDrQqwXUMNelYzMNTmE3A=", + "dev": true + }, + "node_modules/gulp-jsdoc3": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-jsdoc3/-/gulp-jsdoc3-3.0.0.tgz", + "integrity": "sha512-rE2jAwCPA8XFi9g4V3Z3LPhZNjxuMTIYQVMjdqZAQpRfJITLVaUK3xfmiiNTMc7j+fT7pL8Q5yj7ZPRdwCJWNg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "beeper": "^2.0.0", + "debug": "^4.1.1", + "fancy-log": "^1.3.3", + "ink-docstrap": "^1.3.2", + "jsdoc": "^3.6.3", + "map-stream": "0.0.7", + "tmp": "0.1.0" + } + }, + "node_modules/gulp-jsdoc3/node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/gulp-jsdoc3/node_modules/debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/gulp-jsdoc3/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/gulp-rename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/gulp-sourcemaps": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz", + "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", + "dev": true, + "dependencies": { + "@gulp-sourcemaps/identity-map": "^2.0.1", + "@gulp-sourcemaps/map-sources": "^1.0.0", + "acorn": "^6.4.1", + "convert-source-map": "^1.0.0", + "css": "^3.0.0", + "debug-fabulous": "^1.0.0", + "detect-newline": "^2.0.0", + "graceful-fs": "^4.0.0", + "source-map": "^0.6.0", + "strip-bom-string": "^1.0.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gulp-sourcemaps/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/gulp-sourcemaps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "dependencies": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "node_modules/htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + }, + "node_modules/ink-docstrap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ink-docstrap/-/ink-docstrap-1.3.2.tgz", + "integrity": "sha512-STx5orGQU1gfrkoI/fMU7lX6CSP7LBGO10gXNgOZhwKhUqbtNjCkYSewJtNnLmWP1tAGN6oyEpG1HFPw5vpa5Q==", + "dev": true, + "dependencies": { + "moment": "^2.14.1", + "sanitize-html": "^1.13.0" + } + }, + "node_modules/inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "dependencies": { + "source-map": "~0.5.3" + } + }, + "node_modules/insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "dependencies": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "bin": { + "insert-module-globals": "bin/cmd.js" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz", + "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jasmine": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.1.tgz", + "integrity": "sha512-Jqp8P6ZWkTVFGmJwBK46p+kJNrZCdqkQ4GL+PGuBXZwK1fM4ST9BizkYgIwCFqYYqnTizAy6+XG2Ej5dFrej9Q==", + "dev": true, + "dependencies": { + "fast-glob": "^2.2.6", + "jasmine-core": "~3.6.0" + }, + "bin": { + "jasmine": "bin/jasmine.js" + } + }, + "node_modules/jasmine-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", + "dev": true + }, + "node_modules/js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "node_modules/js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.3" + } + }, + "node_modules/jsdoc": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.5.tgz", + "integrity": "sha512-SbY+i9ONuxSK35cgVHaI8O9senTE4CDYAmGSDJ5l3+sfe62Ff4gy96osy6OW84t4K4A8iGnMrlRrsSItSNp3RQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^0.8.2", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.10.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=8.15.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/loader-utils/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "node_modules/lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "node_modules/lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "dependencies": { + "es5-ext": "~0.10.2" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true + }, + "node_modules/marked": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", + "dev": true, + "bin": { + "marked": "bin/marked" + }, + "engines": { + "node": ">= 8.16.2" + } + }, + "node_modules/matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "dependencies": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/md5.js/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "node_modules/memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, + "node_modules/memoizee/node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "dependencies": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mississippi/node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "dev": true, + "dependencies": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "module-deps": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/node-libs-browser/node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/node-libs-browser/node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/node-libs-browser/node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/node-libs-browser/node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "node_modules/node-libs-browser/node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/outpipe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz", + "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=", + "dev": true, + "dependencies": { + "shell-quote": "^1.4.2" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "dependencies": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "node_modules/parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "dependencies": { + "path-platform": "~0.11.15" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=", + "dev": true + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "node_modules/path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss/node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "node_modules/public-encrypt/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "dependencies": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "dependencies": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "node_modules/regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "dependencies": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "dependencies": { + "is-finite": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sanitize-html": { + "version": "1.27.3", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.3.tgz", + "integrity": "sha512-79tcPlgJ3fuK0/TtUCIBdPeQSvktTSTJP9O/dzrteaO98qw5UV6CATh3ZyPjUzv1LtNjHDlhbq9XOXiKf0zA1w==", + "dev": true, + "dependencies": { + "htmlparser2": "^4.1.0", + "lodash": "^4.17.15", + "parse-srcset": "^1.0.2", + "postcss": "^7.0.27" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "dependencies": { + "sver-compat": "^1.5.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dev": true, + "dependencies": { + "fast-safe-stringify": "^2.0.7" + } + }, + "node_modules/shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "node_modules/stream-http": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz", + "integrity": "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==", + "dev": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/stream-http/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/stream-http/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-http/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "dependencies": { + "minimist": "^1.1.0" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "dependencies": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "dependencies": { + "acorn-node": "^1.2.0" + } + }, + "node_modules/taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "serialize-javascript": "^4.0.0", + "schema-utils": "^1.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "dependencies": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + } + }, + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "dependencies": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "dependencies": { + "process": "~0.11.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "dependencies": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "node_modules/tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "dependencies": { + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true, + "bin": { + "umd": "bin/cli.js" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "node_modules/unbox-primitive/node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + }, + "bin": { + "undeclared-identifiers": "bin.js" + } + }, + "node_modules/underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "dev": true + }, + "node_modules/undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "dependencies": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", + "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz", + "integrity": "sha1-lsGjR5uMU5JULGEgKQE7Wyf4i78=", + "dev": true, + "dependencies": { + "bl": "^1.2.1", + "through2": "^2.0.3" + } + }, + "node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-source-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-2.0.0.tgz", + "integrity": "sha1-84pa+53R6Ttl1VBGmsYYKsT1S44=", + "dev": true, + "dependencies": { + "through2": "^2.0.3", + "vinyl": "^2.1.0" + } + }, + "node_modules/vinyl-source-stream/node_modules/clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/vinyl-source-stream/node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "node_modules/vinyl-source-stream/node_modules/replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-source-stream/node_modules/vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "dependencies": { + "source-map": "^0.5.1" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "node_modules/watchify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz", + "integrity": "sha512-2Z04dxwoOeNxa11qzWumBTgSAohTC0+ScuY7XMenPnH+W2lhTcpEOJP4g2EIG/SWeLadPk47x++Yh+8BqPM/lA==", + "dev": true, + "dependencies": { + "anymatch": "^3.1.0", + "browserify": "^17.0.0", + "defined": "^1.0.0", + "chokidar": "^3.4.0", + "outpipe": "^1.1.0", + "through2": "^4.0.2", + "xtend": "^4.0.2" + }, + "bin": { + "watchify": "bin/cmd.js" + }, + "engines": { + "node": ">= 8.10.0" + } + }, + "node_modules/watchify/node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/watchify/node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchify/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchify/node_modules/browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "dependencies": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/watchify/node_modules/browserify/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/watchify/node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/watchify/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchify/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/watchify/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/watchify/node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/watchify/node_modules/insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "dependencies": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "bin": { + "insert-module-globals": "bin/cmd.js" + } + }, + "node_modules/watchify/node_modules/insert-module-globals/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/watchify/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchify/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/watchify/node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/watchify/node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/watchify/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "node_modules/watchify/node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/watchify/node_modules/stream-browserify/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/watchify/node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/watchify/node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/watchify/node_modules/through2/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/watchify/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/watchify/node_modules/util": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", + "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/watchify/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "dependencies": { + "chokidar": "^2.1.8" + } + }, + "node_modules/watchpack/node_modules/anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/watchpack/node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/watchpack/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/watchpack/node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "optional": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + } + }, + "node_modules/watchpack/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/watchpack/node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "optional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/watchpack/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "chrome-trace-event": "^1.0.2", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-stream": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-6.1.2.tgz", + "integrity": "sha512-Bpbsrix1cmWRN705JEg69ErgNAEOpQBvtuWKFW3ZCrLddoPPK6oVpQn4svxNdfedqMLlWA3GLOLvw4c7u63GqA==", + "dev": true, + "dependencies": { + "fancy-log": "^1.3.3", + "lodash.clone": "^4.3.2", + "lodash.some": "^4.2.2", + "memory-fs": "^0.5.0", + "plugin-error": "^1.0.1", + "supports-color": "^7.2.0", + "through": "^2.3.8", + "vinyl": "^2.1.0", + "webpack": "^4.26.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/webpack-stream/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-stream/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", + "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.0", + "es-abstract": "^1.18.0-next.1", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "dependencies": { + "errno": "~0.1.7" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/core": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", + "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.1", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", + "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-module-transforms": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-replace-supers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.11.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz", + "integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@gulp-sourcemaps/identity-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-2.0.1.tgz", + "integrity": "sha512-Tb+nSISZku+eQ4X1lAkevcQa+jknn/OVUgZ3XCxEKIsLsqYuPoJwJOPQeaOk75X3WPftb29GWY1eqE7GLsXb1Q==", + "dev": true, + "requires": { + "acorn": "^6.4.1", + "normalize-path": "^3.0.0", + "postcss": "^7.0.16", + "source-map": "^0.6.0", + "through2": "^3.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + } + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "chalk": "^1.1.3", + "js-tokens": "^3.0.2" + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "babel-helper-evaluate-path": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", + "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", + "dev": true + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-flip-expressions": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", + "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", + "dev": true + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-is-nodes-equiv": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", + "dev": true + }, + "babel-helper-is-void-0": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", + "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", + "dev": true + }, + "babel-helper-mark-eval-scopes": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", + "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", + "dev": true + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-remove-or-void": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", + "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", + "dev": true + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-to-multiple-sequence-expressions": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", + "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", + "dev": true + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-minify-builtins": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", + "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", + "dev": true + }, + "babel-plugin-minify-constant-folding": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", + "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-minify-dead-code-elimination": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz", + "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-mark-eval-scopes": "^0.4.3", + "babel-helper-remove-or-void": "^0.4.3", + "lodash": "^4.17.11" + } + }, + "babel-plugin-minify-flip-comparisons": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", + "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-minify-guarded-expressions": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", + "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3" + } + }, + "babel-plugin-minify-infinity": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", + "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", + "dev": true + }, + "babel-plugin-minify-mangle-names": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", + "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", + "dev": true, + "requires": { + "babel-helper-mark-eval-scopes": "^0.4.3" + } + }, + "babel-plugin-minify-numeric-literals": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", + "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", + "dev": true + }, + "babel-plugin-minify-replace": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", + "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", + "dev": true + }, + "babel-plugin-minify-simplify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", + "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3", + "babel-helper-is-nodes-equiv": "^0.0.1", + "babel-helper-to-multiple-sequence-expressions": "^0.5.0" + } + }, + "babel-plugin-minify-type-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", + "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-inline-consecutive-adds": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", + "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", + "dev": true + }, + "babel-plugin-transform-member-expression-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", + "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", + "dev": true + }, + "babel-plugin-transform-merge-sibling-variables": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", + "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", + "dev": true + }, + "babel-plugin-transform-minify-booleans": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", + "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", + "dev": true + }, + "babel-plugin-transform-property-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", + "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + } + }, + "babel-plugin-transform-regexp-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", + "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", + "dev": true + }, + "babel-plugin-transform-remove-console": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", + "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", + "dev": true + }, + "babel-plugin-transform-remove-debugger": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", + "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", + "dev": true + }, + "babel-plugin-transform-remove-undefined": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", + "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-transform-simplify-comparison-operators": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", + "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", + "dev": true + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-undefined-to-void": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", + "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", + "dev": true + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } + }, + "babel-preset-minify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", + "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==", + "dev": true, + "requires": { + "babel-plugin-minify-builtins": "^0.5.0", + "babel-plugin-minify-constant-folding": "^0.5.0", + "babel-plugin-minify-dead-code-elimination": "^0.5.1", + "babel-plugin-minify-flip-comparisons": "^0.4.3", + "babel-plugin-minify-guarded-expressions": "^0.4.4", + "babel-plugin-minify-infinity": "^0.4.3", + "babel-plugin-minify-mangle-names": "^0.5.0", + "babel-plugin-minify-numeric-literals": "^0.4.3", + "babel-plugin-minify-replace": "^0.5.0", + "babel-plugin-minify-simplify": "^0.5.1", + "babel-plugin-minify-type-constructors": "^0.4.3", + "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", + "babel-plugin-transform-member-expression-literals": "^6.9.4", + "babel-plugin-transform-merge-sibling-variables": "^6.9.4", + "babel-plugin-transform-minify-booleans": "^6.9.4", + "babel-plugin-transform-property-literals": "^6.9.4", + "babel-plugin-transform-regexp-constructors": "^0.4.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "babel-plugin-transform-remove-debugger": "^6.9.4", + "babel-plugin-transform-remove-undefined": "^0.5.0", + "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", + "babel-plugin-transform-undefined-to-void": "^6.9.4", + "lodash": "^4.17.11" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babelify": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz", + "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==", + "dev": true + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "beeper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-2.0.0.tgz", + "integrity": "sha512-+ShExQEewPvKdTUOtCAJmkUAgEyNF0QqgiAhPRE5xLvoFkIPt8xuHKaz1gMLzSMS73beHWs9gbRBngdH61nVWw==", + "dev": true, + "requires": { + "delay": "^4.1.0" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "requires": { + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "JSONStream": "^1.0.3", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "requires": { + "resolve": "^1.17.0" + } + }, + "browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "requires": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "chownr": "^1.1.1", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cached-path-relative": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001114", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001114.tgz", + "integrity": "sha512-ml/zTsfNBM+T1+mjglWRPgVsu2L76GAaADKX5f4t0pbhttEp0WMawJsHDYlFkVZkoA+89uvBRrVrEE4oqenzXQ==", + "dev": true + }, + "catharsis": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.0.0.tgz", + "integrity": "sha1-pikNQT8hemEjL5XkWP84QYz7ARc=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^1.0.6", + "through2": "^2.0.1" + } + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + }, + "dependencies": { + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + } + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + } + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "delay": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-4.4.0.tgz", + "integrity": "sha512-txgOrJu3OdtOfTiEOT2e76dJVfG/1dz2NZ4F0Pyt4UGZJryssMRp5vdM5wQoLwSOBNdrJv3F9PAhp/heqd7vrA==", + "dev": true + }, + "deps-sort": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "docdash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/docdash/-/docdash-1.2.0.tgz", + "integrity": "sha512-IYZbgYthPTspgqYeciRJNPhSwL51yer7HAwDXhF5p+H7mTDbPvY3PCk/QDjNxdPCpWkaJVFC4t7iCNB/t9E5Kw==", + "dev": true + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + }, + "domhandler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", + "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1" + } + }, + "domutils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz", + "integrity": "sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==", + "dev": true, + "requires": { + "dom-serializer": "^0.2.1", + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "electron-to-chromium": { + "version": "1.3.533", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.533.tgz", + "integrity": "sha512-YqAL+NXOzjBnpY+dcOKDlZybJDCOzgsq4koW3fvyty/ldTmsb4QazZpOWmVvZ2m0t5jbBf7L0lIGU3BUipwG+A==", + "dev": true + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } + } + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "dev": true, + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", + "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + } + }, + "gulp-babel-minify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/gulp-babel-minify/-/gulp-babel-minify-0.5.1.tgz", + "integrity": "sha512-qrwtUEbB64nADUUyEciNHGPQ4jYQyDEgorV2NrY3wItISjAhvQ3L2DH/twGNh8rGsEXpCsqItry5RmdVrfCoMg==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "babel-preset-minify": "^0.5.1", + "plugin-error": "^1.0.1", + "through2": "^2.0.3", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + } + } + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + } + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "dependencies": { + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + } + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + }, + "dependencies": { + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + } + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + } + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + }, + "dependencies": { + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + } + } + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "yargs": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", + "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "5.0.0-security.0" + }, + "dependencies": { + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "5.0.0-security.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", + "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "gulp-exit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/gulp-exit/-/gulp-exit-0.0.2.tgz", + "integrity": "sha1-CCMTVIaDrQqwXUMNelYzMNTmE3A=", + "dev": true + }, + "gulp-jsdoc3": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-jsdoc3/-/gulp-jsdoc3-3.0.0.tgz", + "integrity": "sha512-rE2jAwCPA8XFi9g4V3Z3LPhZNjxuMTIYQVMjdqZAQpRfJITLVaUK3xfmiiNTMc7j+fT7pL8Q5yj7ZPRdwCJWNg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1", + "beeper": "^2.0.0", + "debug": "^4.1.1", + "fancy-log": "^1.3.3", + "ink-docstrap": "^1.3.2", + "jsdoc": "^3.6.3", + "map-stream": "0.0.7", + "tmp": "0.1.0" + }, + "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "gulp-rename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "dev": true + }, + "gulp-sourcemaps": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-3.0.0.tgz", + "integrity": "sha512-RqvUckJkuYqy4VaIH60RMal4ZtG0IbQ6PXMNkNsshEGJ9cldUPRb/YCgboYae+CLAs1HQNb4ADTKCx65HInquQ==", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "^2.0.1", + "@gulp-sourcemaps/map-sources": "^1.0.0", + "acorn": "^6.4.1", + "convert-source-map": "^1.0.0", + "css": "^3.0.0", + "debug-fabulous": "^1.0.0", + "detect-newline": "^2.0.0", + "graceful-fs": "^4.0.0", + "source-map": "^0.6.0", + "strip-bom-string": "^1.0.0", + "through2": "^2.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + }, + "ink-docstrap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ink-docstrap/-/ink-docstrap-1.3.2.tgz", + "integrity": "sha512-STx5orGQU1gfrkoI/fMU7lX6CSP7LBGO10gXNgOZhwKhUqbtNjCkYSewJtNnLmWP1tAGN6oyEpG1HFPw5vpa5Q==", + "dev": true, + "requires": { + "moment": "^2.14.1", + "sanitize-html": "^1.13.0" + } + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "~0.5.3" + } + }, + "insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "requires": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz", + "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typed-array": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.5.tgz", + "integrity": "sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.2", + "es-abstract": "^1.18.0-next.2", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "jasmine": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.1.tgz", + "integrity": "sha512-Jqp8P6ZWkTVFGmJwBK46p+kJNrZCdqkQ4GL+PGuBXZwK1fM4ST9BizkYgIwCFqYYqnTizAy6+XG2Ej5dFrej9Q==", + "dev": true, + "requires": { + "fast-glob": "^2.2.6", + "jasmine-core": "~3.6.0" + } + }, + "jasmine-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js2xmlparser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, + "requires": { + "xmlcreate": "^2.0.3" + } + }, + "jsdoc": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.5.tgz", + "integrity": "sha512-SbY+i9ONuxSK35cgVHaI8O9senTE4CDYAmGSDJ5l3+sfe62Ff4gy96osy6OW84t4K4A8iGnMrlRrsSItSNp3RQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "bluebird": "^3.7.2", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.1", + "klaw": "^3.0.0", + "markdown-it": "^10.0.0", + "markdown-it-anchor": "^5.2.7", + "marked": "^0.8.2", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.10.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "labeled-stream-splicer": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "stream-splicer": "^2.0.0" + } + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-it": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz", + "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~2.0.0", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true + }, + "marked": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==", + "dev": true + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "dependencies": { + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + } + } + }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "module-deps": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", + "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==", + "dev": true, + "requires": { + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==", + "dev": true + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "outpipe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz", + "integrity": "sha1-UM+GFjZeh+Ax4ppeyTOaPaRyX6I=", + "dev": true, + "requires": { + "shell-quote": "^1.4.2" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sanitize-html": { + "version": "1.27.3", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.3.tgz", + "integrity": "sha512-79tcPlgJ3fuK0/TtUCIBdPeQSvktTSTJP9O/dzrteaO98qw5UV6CATh3ZyPjUzv1LtNjHDlhbq9XOXiKf0zA1w==", + "dev": true, + "requires": { + "htmlparser2": "^4.1.0", + "lodash": "^4.17.15", + "parse-srcset": "^1.0.2", + "postcss": "^7.0.27" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dev": true, + "requires": { + "fast-safe-stringify": "^2.0.7" + } + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-http": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.1.tgz", + "integrity": "sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "^1.1.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "^1.2.0" + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "serialize-javascript": "^4.0.0", + "schema-utils": "^1.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "~0.11.0" + } + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "tmp": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz", + "integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==", + "dev": true, + "requires": { + "rimraf": "^2.6.3" + } + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "dependencies": { + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + } + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undeclared-identifiers": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==", + "dev": true + }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", + "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz", + "integrity": "sha1-lsGjR5uMU5JULGEgKQE7Wyf4i78=", + "dev": true, + "requires": { + "bl": "^1.2.1", + "through2": "^2.0.3" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-source-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-2.0.0.tgz", + "integrity": "sha1-84pa+53R6Ttl1VBGmsYYKsT1S44=", + "dev": true, + "requires": { + "through2": "^2.0.3", + "vinyl": "^2.1.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + } + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "^0.5.1" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "watchify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz", + "integrity": "sha512-2Z04dxwoOeNxa11qzWumBTgSAohTC0+ScuY7XMenPnH+W2lhTcpEOJP4g2EIG/SWeLadPk47x++Yh+8BqPM/lA==", + "dev": true, + "requires": { + "anymatch": "^3.1.0", + "browserify": "^17.0.0", + "defined": "^1.0.0", + "chokidar": "^3.4.0", + "outpipe": "^1.1.0", + "through2": "^4.0.2", + "xtend": "^4.0.2" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserify": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz", + "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==", + "dev": true, + "requires": { + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^2.0.0", + "browserify-zlib": "~0.2.0", + "buffer": "~5.2.1", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.1", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^3.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.2.1", + "JSONStream": "^1.0.3", + "labeled-stream-splicer": "^2.0.0", + "mkdirp-classic": "^0.5.2", + "module-deps": "^6.2.3", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "^1.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum-object": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^3.0.0", + "stream-http": "^3.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.12.0", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "insert-module-globals": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz", + "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==", + "dev": true, + "requires": { + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "JSONStream": "^1.0.3", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "util": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.3.tgz", + "integrity": "sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "chokidar": "^3.4.1", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "chrome-trace-event": "^1.0.2", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-stream": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/webpack-stream/-/webpack-stream-6.1.2.tgz", + "integrity": "sha512-Bpbsrix1cmWRN705JEg69ErgNAEOpQBvtuWKFW3ZCrLddoPPK6oVpQn4svxNdfedqMLlWA3GLOLvw4c7u63GqA==", + "dev": true, + "requires": { + "fancy-log": "^1.3.3", + "lodash.clone": "^4.3.2", + "lodash.some": "^4.2.2", + "memory-fs": "^0.5.0", + "plugin-error": "^1.0.1", + "supports-color": "^7.2.0", + "through": "^2.3.8", + "vinyl": "^2.1.0", + "webpack": "^4.26.1" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-typed-array": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.4.tgz", + "integrity": "sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "call-bind": "^1.0.0", + "es-abstract": "^1.18.0-next.1", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + } + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xmlcreate": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } +}