diff --git a/package-lock.json b/package-lock.json
index c6052b4e..9748adc8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3055,6 +3055,267 @@
"defer-to-connect": "^1.0.1"
}
},
+ "@types/d3": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/@types/d3/-/d3-6.2.0.tgz",
+ "integrity": "sha512-XhQ6sCTu+CrFLqJMsg/uRPZQrt5FlCPjPE/wvsSBYoaOZ9C1chdJSS9+2oR8+Xtk6DKGewa7/UP5icJRwAryEA==",
+ "dev": true,
+ "requires": {
+ "@types/d3-array": "*",
+ "@types/d3-axis": "*",
+ "@types/d3-brush": "*",
+ "@types/d3-chord": "*",
+ "@types/d3-color": "*",
+ "@types/d3-contour": "*",
+ "@types/d3-delaunay": "*",
+ "@types/d3-dispatch": "*",
+ "@types/d3-drag": "*",
+ "@types/d3-dsv": "*",
+ "@types/d3-ease": "*",
+ "@types/d3-fetch": "*",
+ "@types/d3-force": "*",
+ "@types/d3-format": "*",
+ "@types/d3-geo": "*",
+ "@types/d3-hierarchy": "*",
+ "@types/d3-interpolate": "*",
+ "@types/d3-path": "*",
+ "@types/d3-polygon": "*",
+ "@types/d3-quadtree": "*",
+ "@types/d3-random": "*",
+ "@types/d3-scale": "*",
+ "@types/d3-scale-chromatic": "*",
+ "@types/d3-selection": "*",
+ "@types/d3-shape": "*",
+ "@types/d3-time": "*",
+ "@types/d3-time-format": "*",
+ "@types/d3-timer": "*",
+ "@types/d3-transition": "*",
+ "@types/d3-zoom": "*"
+ }
+ },
+ "@types/d3-array": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-2.8.0.tgz",
+ "integrity": "sha512-Q0ubcGHAmCRPh90/hoYB4eKWhxYKUxphwSeQrlz2tiabQ8S9zqhaE2CZJtCaLH2cjqKcjr52WPvmOA7ha0O4ZA==",
+ "dev": true
+ },
+ "@types/d3-axis": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-2.0.0.tgz",
+ "integrity": "sha512-gUdlEwGBLl3tXGiBnBNmNzph9W3bCfa4tBgWZD60Z1eDQKTY4zyCAcZ3LksignGfKawYatmDYcBdjJ5h/54sqA==",
+ "dev": true,
+ "requires": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "@types/d3-brush": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-2.1.0.tgz",
+ "integrity": "sha512-rLQqxQeXWF4ArXi81GlV8HBNwJw9EDpz0jcWvvzv548EDE4tXrayBTOHYi/8Q4FZ/Df8PGXFzxpAVQmJMjOtvQ==",
+ "dev": true,
+ "requires": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "@types/d3-chord": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-2.0.0.tgz",
+ "integrity": "sha512-3nHsLY7lImpZlM/hrPeDqqW2a+lRXXoHsG54QSurDGihZAIE/doQlohs0evoHrWOJqXyn4A4xbSVEtXnMEZZiw==",
+ "dev": true
+ },
+ "@types/d3-color": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.1.tgz",
+ "integrity": "sha512-u7LTCL7RnaavFSmob2rIAJLNwu50i6gFwY9cHFr80BrQURYQBRkJ+Yv47nA3Fm7FeRhdWTiVTeqvSeOuMAOzBQ==",
+ "dev": true
+ },
+ "@types/d3-contour": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-2.0.0.tgz",
+ "integrity": "sha512-PS9UO6zBQqwHXsocbpdzZFONgK1oRUgWtjjh/iz2vM06KaXLInLiKZ9e3OLBRerc1cU2uJYpO+8zOnb6frvCGQ==",
+ "dev": true,
+ "requires": {
+ "@types/d3-array": "*",
+ "@types/geojson": "*"
+ }
+ },
+ "@types/d3-delaunay": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-5.3.0.tgz",
+ "integrity": "sha512-gJYcGxLu0xDZPccbUe32OUpeaNtd1Lz0NYJtko6ZLMyG2euF4pBzrsQXms67LHZCDFzzszw+dMhSL/QAML3bXw==",
+ "dev": true
+ },
+ "@types/d3-dispatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
+ "integrity": "sha512-Sh0KW6z/d7uxssD7K4s4uCSzlEG/+SP+U47q098NVdOfFvUKNTvKAIV4XqjxsUuhE/854ARAREHOxkr9gQOCyg==",
+ "dev": true
+ },
+ "@types/d3-drag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-2.0.0.tgz",
+ "integrity": "sha512-VaUJPjbMnDn02tcRqsHLRAX5VjcRIzCjBfeXTLGe6QjMn5JccB5Cz4ztMRXMJfkbC45ovgJFWuj6DHvWMX1thA==",
+ "dev": true,
+ "requires": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "@types/d3-dsv": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-2.0.1.tgz",
+ "integrity": "sha512-wovgiG9Mgkr/SZ/m/c0m+RwrIT4ozsuCWeLxJyoObDWsie2DeQT4wzMdHZPR9Ya5oZLQT3w3uSl0NehG0+0dCA==",
+ "dev": true
+ },
+ "@types/d3-ease": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-2.0.0.tgz",
+ "integrity": "sha512-6aZrTyX5LG+ptofVHf+gTsThLRY1nhLotJjgY4drYqk1OkJMu2UvuoZRlPw2fffjRHeYepue3/fxTufqKKmvsA==",
+ "dev": true
+ },
+ "@types/d3-fetch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-2.0.0.tgz",
+ "integrity": "sha512-WnLepGtxepFfXRdPI8I5FTgNiHn9p4vMTTqaNCzJJfAswXx0rOY2jjeolzEU063em3iJmGZ+U79InnEeFOrCRw==",
+ "dev": true,
+ "requires": {
+ "@types/d3-dsv": "*"
+ }
+ },
+ "@types/d3-force": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-2.1.0.tgz",
+ "integrity": "sha512-LGDtC2YADu8OBniq9EBx/MOsXsMcJbEkmfSpXuz6oVdRamB+3CLCiq5EKFPEILGZQckkilGFq1ZTJ7kc289k+Q==",
+ "dev": true
+ },
+ "@types/d3-format": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-2.0.0.tgz",
+ "integrity": "sha512-uagdkftxnGkO4pZw5jEYOM5ZnZOEsh7z8j11Qxk85UkB2RzfUUxRl7R9VvvJZHwKn8l+x+rpS77Nusq7FkFmIg==",
+ "dev": true
+ },
+ "@types/d3-geo": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-2.0.0.tgz",
+ "integrity": "sha512-DHHgYXW36lnAEQMYU2udKVOxxljHrn2EdOINeSC9jWCAXwOnGn7A19B8sNsHqgpu4F7O2bSD7//cqBXD3W0Deg==",
+ "dev": true,
+ "requires": {
+ "@types/geojson": "*"
+ }
+ },
+ "@types/d3-hierarchy": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz",
+ "integrity": "sha512-YxdskUvwzqggpnSnDQj4KVkicgjpkgXn/g/9M9iGsiToLS3nG6Ytjo1FoYhYVAAElV/fJBGVL3cQ9Hb7tcv+lw==",
+ "dev": true
+ },
+ "@types/d3-interpolate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-2.0.0.tgz",
+ "integrity": "sha512-Wt1v2zTlEN8dSx8hhx6MoOhWQgTkz0Ukj7owAEIOF2QtI0e219paFX9rf/SLOr/UExWb1TcUzatU8zWwFby6gg==",
+ "dev": true,
+ "requires": {
+ "@types/d3-color": "*"
+ }
+ },
+ "@types/d3-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-2.0.0.tgz",
+ "integrity": "sha512-tXcR/9OtDdeCIsyl6eTNHC3XOAOdyc6ceF3QGBXOd9jTcK+ex/ecr00p9L9362e/op3UEPpxrToi1FHrtTSj7Q==",
+ "dev": true
+ },
+ "@types/d3-polygon": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-2.0.0.tgz",
+ "integrity": "sha512-fISnMd8ePED1G4aa4V974Jmt+ajHSgPoxMa2D0ULxMybpx0Vw4WEzhQEaMIrL3hM8HVRcKTx669I+dTy/4PhAw==",
+ "dev": true
+ },
+ "@types/d3-quadtree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-2.0.0.tgz",
+ "integrity": "sha512-YZuJuGBnijD0H+98xMJD4oZXgv/umPXy5deu3IimYTPGH3Kr8Th6iQUff0/6S80oNBD7KtOuIHwHUCymUiRoeQ==",
+ "dev": true
+ },
+ "@types/d3-random": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-2.2.0.tgz",
+ "integrity": "sha512-Hjfj9m68NmYZzushzEG7etPvKH/nj9b9s9+qtkNG3/dbRBjQZQg1XS6nRuHJcCASTjxXlyXZnKu2gDxyQIIu9A==",
+ "dev": true
+ },
+ "@types/d3-scale": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.2.2.tgz",
+ "integrity": "sha512-qpQe8G02tzUwt9sdWX1h8A/W0Q1+N48wMnYXVOkrzeLUkCfvzJYV9Ee3aORCS4dN4ONRLFmMvaXdziQ29XGLjQ==",
+ "dev": true,
+ "requires": {
+ "@types/d3-time": "*"
+ }
+ },
+ "@types/d3-scale-chromatic": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz",
+ "integrity": "sha512-Y62+2clOwZoKua84Ha0xU77w7lePiaBoTjXugT4l8Rd5LAk+Mn/ZDtrgs087a+B5uJ3jYUHHtKw5nuEzp0WBHw==",
+ "dev": true
+ },
+ "@types/d3-selection": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-2.0.0.tgz",
+ "integrity": "sha512-EF0lWZ4tg7oDFg4YQFlbOU3936e3a9UmoQ2IXlBy1+cv2c2Pv7knhKUzGlH5Hq2sF/KeDTH1amiRPey2rrLMQA==",
+ "dev": true
+ },
+ "@types/d3-shape": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-2.0.0.tgz",
+ "integrity": "sha512-NLzD02m5PiD1KLEDjLN+MtqEcFYn4ZL9+Rqc9ZwARK1cpKZXd91zBETbe6wpBB6Ia0D0VZbpmbW3+BsGPGnCpA==",
+ "dev": true,
+ "requires": {
+ "@types/d3-path": "^1"
+ },
+ "dependencies": {
+ "@types/d3-path": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz",
+ "integrity": "sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==",
+ "dev": true
+ }
+ }
+ },
+ "@types/d3-time": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-2.0.0.tgz",
+ "integrity": "sha512-Abz8bTzy8UWDeYs9pCa3D37i29EWDjNTjemdk0ei1ApYVNqulYlGUKip/jLOpogkPSsPz/GvZCYiC7MFlEk0iQ==",
+ "dev": true
+ },
+ "@types/d3-time-format": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-3.0.0.tgz",
+ "integrity": "sha512-UpLg1mn/8PLyjr+J/JwdQJM/GzysMvv2CS8y+WYAL5K0+wbvXv/pPSLEfdNaprCZsGcXTxPsFMy8QtkYv9ueew==",
+ "dev": true
+ },
+ "@types/d3-timer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.0.tgz",
+ "integrity": "sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg==",
+ "dev": true
+ },
+ "@types/d3-transition": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-2.0.0.tgz",
+ "integrity": "sha512-UJDzI98utcZQUJt3uIit/Ho0/eBIANzrWJrTmi4+TaKIyWL2iCu7ShP0o4QajCskhyjOA7C8+4CE3b1YirTzEQ==",
+ "dev": true,
+ "requires": {
+ "@types/d3-selection": "*"
+ }
+ },
+ "@types/d3-zoom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-2.0.0.tgz",
+ "integrity": "sha512-daL0PJm4yT0ISTGa7p2lHX0kvv9FO/IR1ooWbHR/7H4jpbaKiLux5FslyS/OvISPiJ5SXb4sOqYhO6fMB6hKRw==",
+ "dev": true,
+ "requires": {
+ "@types/d3-interpolate": "*",
+ "@types/d3-selection": "*"
+ }
+ },
"@types/duplexify": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.0.tgz",
@@ -3073,6 +3334,12 @@
"@types/node": "*"
}
},
+ "@types/geojson": {
+ "version": "7946.0.7",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
+ "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==",
+ "dev": true
+ },
"@types/glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -5304,8 +5571,7 @@
"commander": {
"version": "2.14.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
- "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao=",
- "dev": true
+ "integrity": "sha1-IjUSPjevjKPGXfRbAm29NXsBuao="
},
"commondir": {
"version": "1.0.1",
@@ -6099,6 +6365,266 @@
"type": "^1.0.1"
}
},
+ "d3": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/d3/-/d3-6.4.0.tgz",
+ "integrity": "sha512-A8uZ7IPQSNmc5YZtrzbkNepsChV6vj7rZj9A1LV33GmDeZ0mMSgO1nxbksbN9ciTWR1YySUD4aJc3wBGb8xdrg==",
+ "requires": {
+ "d3-array": "2",
+ "d3-axis": "2",
+ "d3-brush": "2",
+ "d3-chord": "2",
+ "d3-color": "2",
+ "d3-contour": "2",
+ "d3-delaunay": "5",
+ "d3-dispatch": "2",
+ "d3-drag": "2",
+ "d3-dsv": "2",
+ "d3-ease": "2",
+ "d3-fetch": "2",
+ "d3-force": "2",
+ "d3-format": "2",
+ "d3-geo": "2",
+ "d3-hierarchy": "2",
+ "d3-interpolate": "2",
+ "d3-path": "2",
+ "d3-polygon": "2",
+ "d3-quadtree": "2",
+ "d3-random": "2",
+ "d3-scale": "3",
+ "d3-scale-chromatic": "2",
+ "d3-selection": "2",
+ "d3-shape": "2",
+ "d3-time": "2",
+ "d3-time-format": "3",
+ "d3-timer": "2",
+ "d3-transition": "2",
+ "d3-zoom": "2"
+ }
+ },
+ "d3-array": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.10.0.tgz",
+ "integrity": "sha512-TygE7/GvpL0092Pa/cS/kcyQ4E+I8KCkw3uCpQOFc4xi4IWNE67xST56H1Tz/FTYUqABULSEAmeLrGAmuLN8Xg==",
+ "requires": {
+ "internmap": "^1.0.0"
+ }
+ },
+ "d3-axis": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-2.0.0.tgz",
+ "integrity": "sha512-9nzB0uePtb+u9+dWir+HTuEAKJOEUYJoEwbJPsZ1B4K3iZUgzJcSENQ05Nj7S4CIfbZZ8/jQGoUzGKFznBhiiQ=="
+ },
+ "d3-brush": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-2.1.0.tgz",
+ "integrity": "sha512-cHLLAFatBATyIKqZOkk/mDHUbzne2B3ZwxkzMHvFTCZCmLaXDpZRihQSn8UNXTkGD/3lb/W2sQz0etAftmHMJQ==",
+ "requires": {
+ "d3-dispatch": "1 - 2",
+ "d3-drag": "2",
+ "d3-interpolate": "1 - 2",
+ "d3-selection": "2",
+ "d3-transition": "2"
+ }
+ },
+ "d3-chord": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-2.0.0.tgz",
+ "integrity": "sha512-D5PZb7EDsRNdGU4SsjQyKhja8Zgu+SHZfUSO5Ls8Wsn+jsAKUUGkcshLxMg9HDFxG3KqavGWaWkJ8EpU8ojuig==",
+ "requires": {
+ "d3-path": "1 - 2"
+ }
+ },
+ "d3-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
+ "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
+ },
+ "d3-contour": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-2.0.0.tgz",
+ "integrity": "sha512-9unAtvIaNk06UwqBmvsdHX7CZ+NPDZnn8TtNH1myW93pWJkhsV25JcgnYAu0Ck5Veb1DHiCv++Ic5uvJ+h50JA==",
+ "requires": {
+ "d3-array": "2"
+ }
+ },
+ "d3-delaunay": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-5.3.0.tgz",
+ "integrity": "sha512-amALSrOllWVLaHTnDLHwMIiz0d1bBu9gZXd1FiLfXf8sHcX9jrcj81TVZOqD4UX7MgBZZ07c8GxzEgBpJqc74w==",
+ "requires": {
+ "delaunator": "4"
+ }
+ },
+ "d3-dispatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
+ "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
+ },
+ "d3-drag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz",
+ "integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==",
+ "requires": {
+ "d3-dispatch": "1 - 2",
+ "d3-selection": "2"
+ }
+ },
+ "d3-dsv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-2.0.0.tgz",
+ "integrity": "sha512-E+Pn8UJYx9mViuIUkoc93gJGGYut6mSDKy2+XaPwccwkRGlR+LO97L2VCCRjQivTwLHkSnAJG7yo00BWY6QM+w==",
+ "requires": {
+ "commander": "2",
+ "iconv-lite": "0.4",
+ "rw": "1"
+ }
+ },
+ "d3-ease": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz",
+ "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ=="
+ },
+ "d3-fetch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-2.0.0.tgz",
+ "integrity": "sha512-TkYv/hjXgCryBeNKiclrwqZH7Nb+GaOwo3Neg24ZVWA3MKB+Rd+BY84Nh6tmNEMcjUik1CSUWjXYndmeO6F7sw==",
+ "requires": {
+ "d3-dsv": "1 - 2"
+ }
+ },
+ "d3-force": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz",
+ "integrity": "sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==",
+ "requires": {
+ "d3-dispatch": "1 - 2",
+ "d3-quadtree": "1 - 2",
+ "d3-timer": "1 - 2"
+ }
+ },
+ "d3-format": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",
+ "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA=="
+ },
+ "d3-geo": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.1.tgz",
+ "integrity": "sha512-M6yzGbFRfxzNrVhxDJXzJqSLQ90q1cCyb3EWFZ1LF4eWOBYxFypw7I/NFVBNXKNqxv1bqLathhYvdJ6DC+th3A==",
+ "requires": {
+ "d3-array": ">=2.5"
+ }
+ },
+ "d3-hierarchy": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz",
+ "integrity": "sha512-SwIdqM3HxQX2214EG9GTjgmCc/mbSx4mQBn+DuEETubhOw6/U3fmnji4uCVrmzOydMHSO1nZle5gh6HB/wdOzw=="
+ },
+ "d3-interpolate": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
+ "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
+ "requires": {
+ "d3-color": "1 - 2"
+ }
+ },
+ "d3-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz",
+ "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA=="
+ },
+ "d3-polygon": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-2.0.0.tgz",
+ "integrity": "sha512-MsexrCK38cTGermELs0cO1d79DcTsQRN7IWMJKczD/2kBjzNXxLUWP33qRF6VDpiLV/4EI4r6Gs0DAWQkE8pSQ=="
+ },
+ "d3-quadtree": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz",
+ "integrity": "sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw=="
+ },
+ "d3-random": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-2.2.2.tgz",
+ "integrity": "sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw=="
+ },
+ "d3-scale": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.3.tgz",
+ "integrity": "sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g==",
+ "requires": {
+ "d3-array": "^2.3.0",
+ "d3-format": "1 - 2",
+ "d3-interpolate": "1.2.0 - 2",
+ "d3-time": "1 - 2",
+ "d3-time-format": "2 - 3"
+ }
+ },
+ "d3-scale-chromatic": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz",
+ "integrity": "sha512-LLqy7dJSL8yDy7NRmf6xSlsFZ6zYvJ4BcWFE4zBrOPnQERv9zj24ohnXKRbyi9YHnYV+HN1oEO3iFK971/gkzA==",
+ "requires": {
+ "d3-color": "1 - 2",
+ "d3-interpolate": "1 - 2"
+ }
+ },
+ "d3-selection": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz",
+ "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA=="
+ },
+ "d3-shape": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.0.0.tgz",
+ "integrity": "sha512-djpGlA779ua+rImicYyyjnOjeubyhql1Jyn1HK0bTyawuH76UQRWXd+pftr67H6Fa8hSwetkgb/0id3agKWykw==",
+ "requires": {
+ "d3-path": "1 - 2"
+ }
+ },
+ "d3-time": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.0.0.tgz",
+ "integrity": "sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q=="
+ },
+ "d3-time-format": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz",
+ "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==",
+ "requires": {
+ "d3-time": "1 - 2"
+ }
+ },
+ "d3-timer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz",
+ "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA=="
+ },
+ "d3-transition": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz",
+ "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==",
+ "requires": {
+ "d3-color": "1 - 2",
+ "d3-dispatch": "1 - 2",
+ "d3-ease": "1 - 2",
+ "d3-interpolate": "1 - 2",
+ "d3-timer": "1 - 2"
+ }
+ },
+ "d3-zoom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz",
+ "integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==",
+ "requires": {
+ "d3-dispatch": "1 - 2",
+ "d3-drag": "2",
+ "d3-interpolate": "1 - 2",
+ "d3-selection": "2",
+ "d3-transition": "2"
+ }
+ },
"damerau-levenshtein": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz",
@@ -6335,6 +6861,11 @@
}
}
},
+ "delaunator": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz",
+ "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag=="
+ },
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -9269,7 +9800,6 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
@@ -9636,6 +10166,11 @@
"ipaddr.js": "^1.9.0"
}
},
+ "internmap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.0.tgz",
+ "integrity": "sha512-SdoDWwNOTE2n4JWUsLn4KXZGuZPjPF9yyOGc8bnfWnBQh7BD/l80rzSznKc/r4Y0aQ7z3RTk9X+tV4tHBpu+dA=="
+ },
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@@ -15097,6 +15632,11 @@
"aproba": "^1.1.1"
}
},
+ "rw": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
+ "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
+ },
"rxjs": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
@@ -15129,8 +15669,7 @@
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sass": {
"version": "1.27.0",
diff --git a/package.json b/package.json
index 3fac638a..6e380b00 100644
--- a/package.json
+++ b/package.json
@@ -23,6 +23,7 @@
"@angular/platform-browser-dynamic": "11.0.2",
"@angular/router": "11.0.2",
"core-js": "^2.6.12",
+ "d3": "^6.4.0",
"firebase": "^8.2.1",
"rxjs": "^6.6.3",
"tslib": "^2.1.0",
@@ -36,6 +37,7 @@
"@angular/cli": "11.0.2",
"@angular/compiler-cli": "11.0.2",
"@angular/language-service": "11.0.2",
+ "@types/d3": "^6.2.0",
"@types/jasmine": "~3.6.0",
"@types/jasminewd2": "^2.0.8",
"@types/node": "^12.19.12",
diff --git a/src/app/objects/factions/d3-graph/d3-graph.component.css b/src/app/objects/factions/d3-graph/d3-graph.component.css
new file mode 100644
index 00000000..e69de29b
diff --git a/src/app/objects/factions/d3-graph/d3-graph.component.html b/src/app/objects/factions/d3-graph/d3-graph.component.html
new file mode 100644
index 00000000..7448df1d
--- /dev/null
+++ b/src/app/objects/factions/d3-graph/d3-graph.component.html
@@ -0,0 +1,8 @@
+
+
+Bar Chart
+
\ No newline at end of file
diff --git a/src/app/objects/factions/d3-graph/d3-graph.component.spec.ts b/src/app/objects/factions/d3-graph/d3-graph.component.spec.ts
new file mode 100644
index 00000000..1738b6b0
--- /dev/null
+++ b/src/app/objects/factions/d3-graph/d3-graph.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { D3GraphComponent } from './d3-graph.component';
+
+describe('D3GraphComponent', () => {
+ let component: D3GraphComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ D3GraphComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(D3GraphComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/objects/factions/d3-graph/d3-graph.component.ts b/src/app/objects/factions/d3-graph/d3-graph.component.ts
new file mode 100644
index 00000000..1b978919
--- /dev/null
+++ b/src/app/objects/factions/d3-graph/d3-graph.component.ts
@@ -0,0 +1,554 @@
+import { Component, OnInit } from '@angular/core';
+import * as d3 from 'd3';
+
+@Component({
+ selector: 'lux-d3-graph',
+ templateUrl: './d3-graph.component.html',
+ styleUrls: ['./d3-graph.component.css']
+})
+export class D3GraphComponent implements OnInit {
+ private data = {
+ "nodes": [
+ { "id": "Myriel", "group": 1 },
+ { "id": "Napoleon", "group": 1 },
+ { "id": "Mlle.Baptistine", "group": 1 },
+ { "id": "Mme.Magloire", "group": 1 },
+ { "id": "CountessdeLo", "group": 1 },
+ { "id": "Geborand", "group": 1 },
+ { "id": "Champtercier", "group": 1 },
+ { "id": "Cravatte", "group": 1 },
+ { "id": "Count", "group": 1 },
+ { "id": "OldMan", "group": 1 },
+ { "id": "Labarre", "group": 2 },
+ { "id": "Valjean", "group": 2 },
+ { "id": "Marguerite", "group": 3 },
+ { "id": "Mme.deR", "group": 2 },
+ { "id": "Isabeau", "group": 2 },
+ { "id": "Gervais", "group": 2 },
+ { "id": "Tholomyes", "group": 3 },
+ { "id": "Listolier", "group": 3 },
+ { "id": "Fameuil", "group": 3 },
+ { "id": "Blacheville", "group": 3 },
+ { "id": "Favourite", "group": 3 },
+ { "id": "Dahlia", "group": 3 },
+ { "id": "Zephine", "group": 3 },
+ { "id": "Fantine", "group": 3 },
+ { "id": "Mme.Thenardier", "group": 4 },
+ { "id": "Thenardier", "group": 4 },
+ { "id": "Cosette", "group": 5 },
+ { "id": "Javert", "group": 4 },
+ { "id": "Fauchelevent", "group": 0 },
+ { "id": "Bamatabois", "group": 2 },
+ { "id": "Perpetue", "group": 3 },
+ { "id": "Simplice", "group": 2 },
+ { "id": "Scaufflaire", "group": 2 },
+ { "id": "Woman1", "group": 2 },
+ { "id": "Judge", "group": 2 },
+ { "id": "Champmathieu", "group": 2 },
+ { "id": "Brevet", "group": 2 },
+ { "id": "Chenildieu", "group": 2 },
+ { "id": "Cochepaille", "group": 2 },
+ { "id": "Pontmercy", "group": 4 },
+ { "id": "Boulatruelle", "group": 6 },
+ { "id": "Eponine", "group": 4 },
+ { "id": "Anzelma", "group": 4 },
+ { "id": "Woman2", "group": 5 },
+ { "id": "MotherInnocent", "group": 0 },
+ { "id": "Gribier", "group": 0 },
+ { "id": "Jondrette", "group": 7 },
+ { "id": "Mme.Burgon", "group": 7 },
+ { "id": "Gavroche", "group": 8 },
+ { "id": "Gillenormand", "group": 5 },
+ { "id": "Magnon", "group": 5 },
+ { "id": "Mlle.Gillenormand", "group": 5 },
+ { "id": "Mme.Pontmercy", "group": 5 },
+ { "id": "Mlle.Vaubois", "group": 5 },
+ { "id": "Lt.Gillenormand", "group": 5 },
+ { "id": "Marius", "group": 8 },
+ { "id": "BaronessT", "group": 5 },
+ { "id": "Mabeuf", "group": 8 },
+ { "id": "Enjolras", "group": 8 },
+ { "id": "Combeferre", "group": 8 },
+ { "id": "Prouvaire", "group": 8 },
+ { "id": "Feuilly", "group": 8 },
+ { "id": "Courfeyrac", "group": 8 },
+ { "id": "Bahorel", "group": 8 },
+ { "id": "Bossuet", "group": 8 },
+ { "id": "Joly", "group": 8 },
+ { "id": "Grantaire", "group": 8 },
+ { "id": "MotherPlutarch", "group": 9 },
+ { "id": "Gueulemer", "group": 4 },
+ { "id": "Babet", "group": 4 },
+ { "id": "Claquesous", "group": 4 },
+ { "id": "Montparnasse", "group": 4 },
+ { "id": "Toussaint", "group": 5 },
+ { "id": "Child1", "group": 10 },
+ { "id": "Child2", "group": 10 },
+ { "id": "Brujon", "group": 4 },
+ { "id": "Mme.Hucheloup", "group": 8 }
+ ],
+ "links": [
+ { "source": "Napoleon", "target": "Myriel", "value": 1 },
+ { "source": "Mlle.Baptistine", "target": "Myriel", "value": 8 },
+ { "source": "Mme.Magloire", "target": "Myriel", "value": 10 },
+ { "source": "Mme.Magloire", "target": "Mlle.Baptistine", "value": 6 },
+ { "source": "CountessdeLo", "target": "Myriel", "value": 1 },
+ { "source": "Geborand", "target": "Myriel", "value": 1 },
+ { "source": "Champtercier", "target": "Myriel", "value": 1 },
+ { "source": "Cravatte", "target": "Myriel", "value": 1 },
+ { "source": "Count", "target": "Myriel", "value": 2 },
+ { "source": "OldMan", "target": "Myriel", "value": 1 },
+ { "source": "Valjean", "target": "Labarre", "value": 1 },
+ { "source": "Valjean", "target": "Mme.Magloire", "value": 3 },
+ { "source": "Valjean", "target": "Mlle.Baptistine", "value": 3 },
+ { "source": "Valjean", "target": "Myriel", "value": 5 },
+ { "source": "Marguerite", "target": "Valjean", "value": 1 },
+ { "source": "Mme.deR", "target": "Valjean", "value": 1 },
+ { "source": "Isabeau", "target": "Valjean", "value": 1 },
+ { "source": "Gervais", "target": "Valjean", "value": 1 },
+ { "source": "Listolier", "target": "Tholomyes", "value": 4 },
+ { "source": "Fameuil", "target": "Tholomyes", "value": 4 },
+ { "source": "Fameuil", "target": "Listolier", "value": 4 },
+ { "source": "Blacheville", "target": "Tholomyes", "value": 4 },
+ { "source": "Blacheville", "target": "Listolier", "value": 4 },
+ { "source": "Blacheville", "target": "Fameuil", "value": 4 },
+ { "source": "Favourite", "target": "Tholomyes", "value": 3 },
+ { "source": "Favourite", "target": "Listolier", "value": 3 },
+ { "source": "Favourite", "target": "Fameuil", "value": 3 },
+ { "source": "Favourite", "target": "Blacheville", "value": 4 },
+ { "source": "Dahlia", "target": "Tholomyes", "value": 3 },
+ { "source": "Dahlia", "target": "Listolier", "value": 3 },
+ { "source": "Dahlia", "target": "Fameuil", "value": 3 },
+ { "source": "Dahlia", "target": "Blacheville", "value": 3 },
+ { "source": "Dahlia", "target": "Favourite", "value": 5 },
+ { "source": "Zephine", "target": "Tholomyes", "value": 3 },
+ { "source": "Zephine", "target": "Listolier", "value": 3 },
+ { "source": "Zephine", "target": "Fameuil", "value": 3 },
+ { "source": "Zephine", "target": "Blacheville", "value": 3 },
+ { "source": "Zephine", "target": "Favourite", "value": 4 },
+ { "source": "Zephine", "target": "Dahlia", "value": 4 },
+ { "source": "Fantine", "target": "Tholomyes", "value": 3 },
+ { "source": "Fantine", "target": "Listolier", "value": 3 },
+ { "source": "Fantine", "target": "Fameuil", "value": 3 },
+ { "source": "Fantine", "target": "Blacheville", "value": 3 },
+ { "source": "Fantine", "target": "Favourite", "value": 4 },
+ { "source": "Fantine", "target": "Dahlia", "value": 4 },
+ { "source": "Fantine", "target": "Zephine", "value": 4 },
+ { "source": "Fantine", "target": "Marguerite", "value": 2 },
+ { "source": "Fantine", "target": "Valjean", "value": 9 },
+ { "source": "Mme.Thenardier", "target": "Fantine", "value": 2 },
+ { "source": "Mme.Thenardier", "target": "Valjean", "value": 7 },
+ { "source": "Thenardier", "target": "Mme.Thenardier", "value": 13 },
+ { "source": "Thenardier", "target": "Fantine", "value": 1 },
+ { "source": "Thenardier", "target": "Valjean", "value": 12 },
+ { "source": "Cosette", "target": "Mme.Thenardier", "value": 4 },
+ { "source": "Cosette", "target": "Valjean", "value": 31 },
+ { "source": "Cosette", "target": "Tholomyes", "value": 1 },
+ { "source": "Cosette", "target": "Thenardier", "value": 1 },
+ { "source": "Javert", "target": "Valjean", "value": 17 },
+ { "source": "Javert", "target": "Fantine", "value": 5 },
+ { "source": "Javert", "target": "Thenardier", "value": 5 },
+ { "source": "Javert", "target": "Mme.Thenardier", "value": 1 },
+ { "source": "Javert", "target": "Cosette", "value": 1 },
+ { "source": "Fauchelevent", "target": "Valjean", "value": 8 },
+ { "source": "Fauchelevent", "target": "Javert", "value": 1 },
+ { "source": "Bamatabois", "target": "Fantine", "value": 1 },
+ { "source": "Bamatabois", "target": "Javert", "value": 1 },
+ { "source": "Bamatabois", "target": "Valjean", "value": 2 },
+ { "source": "Perpetue", "target": "Fantine", "value": 1 },
+ { "source": "Simplice", "target": "Perpetue", "value": 2 },
+ { "source": "Simplice", "target": "Valjean", "value": 3 },
+ { "source": "Simplice", "target": "Fantine", "value": 2 },
+ { "source": "Simplice", "target": "Javert", "value": 1 },
+ { "source": "Scaufflaire", "target": "Valjean", "value": 1 },
+ { "source": "Woman1", "target": "Valjean", "value": 2 },
+ { "source": "Woman1", "target": "Javert", "value": 1 },
+ { "source": "Judge", "target": "Valjean", "value": 3 },
+ { "source": "Judge", "target": "Bamatabois", "value": 2 },
+ { "source": "Champmathieu", "target": "Valjean", "value": 3 },
+ { "source": "Champmathieu", "target": "Judge", "value": 3 },
+ { "source": "Champmathieu", "target": "Bamatabois", "value": 2 },
+ { "source": "Brevet", "target": "Judge", "value": 2 },
+ { "source": "Brevet", "target": "Champmathieu", "value": 2 },
+ { "source": "Brevet", "target": "Valjean", "value": 2 },
+ { "source": "Brevet", "target": "Bamatabois", "value": 1 },
+ { "source": "Chenildieu", "target": "Judge", "value": 2 },
+ { "source": "Chenildieu", "target": "Champmathieu", "value": 2 },
+ { "source": "Chenildieu", "target": "Brevet", "value": 2 },
+ { "source": "Chenildieu", "target": "Valjean", "value": 2 },
+ { "source": "Chenildieu", "target": "Bamatabois", "value": 1 },
+ { "source": "Cochepaille", "target": "Judge", "value": 2 },
+ { "source": "Cochepaille", "target": "Champmathieu", "value": 2 },
+ { "source": "Cochepaille", "target": "Brevet", "value": 2 },
+ { "source": "Cochepaille", "target": "Chenildieu", "value": 2 },
+ { "source": "Cochepaille", "target": "Valjean", "value": 2 },
+ { "source": "Cochepaille", "target": "Bamatabois", "value": 1 },
+ { "source": "Pontmercy", "target": "Thenardier", "value": 1 },
+ { "source": "Boulatruelle", "target": "Thenardier", "value": 1 },
+ { "source": "Eponine", "target": "Mme.Thenardier", "value": 2 },
+ { "source": "Eponine", "target": "Thenardier", "value": 3 },
+ { "source": "Anzelma", "target": "Eponine", "value": 2 },
+ { "source": "Anzelma", "target": "Thenardier", "value": 2 },
+ { "source": "Anzelma", "target": "Mme.Thenardier", "value": 1 },
+ { "source": "Woman2", "target": "Valjean", "value": 3 },
+ { "source": "Woman2", "target": "Cosette", "value": 1 },
+ { "source": "Woman2", "target": "Javert", "value": 1 },
+ { "source": "MotherInnocent", "target": "Fauchelevent", "value": 3 },
+ { "source": "MotherInnocent", "target": "Valjean", "value": 1 },
+ { "source": "Gribier", "target": "Fauchelevent", "value": 2 },
+ { "source": "Mme.Burgon", "target": "Jondrette", "value": 1 },
+ { "source": "Gavroche", "target": "Mme.Burgon", "value": 2 },
+ { "source": "Gavroche", "target": "Thenardier", "value": 1 },
+ { "source": "Gavroche", "target": "Javert", "value": 1 },
+ { "source": "Gavroche", "target": "Valjean", "value": 1 },
+ { "source": "Gillenormand", "target": "Cosette", "value": 3 },
+ { "source": "Gillenormand", "target": "Valjean", "value": 2 },
+ { "source": "Magnon", "target": "Gillenormand", "value": 1 },
+ { "source": "Magnon", "target": "Mme.Thenardier", "value": 1 },
+ { "source": "Mlle.Gillenormand", "target": "Gillenormand", "value": 9 },
+ { "source": "Mlle.Gillenormand", "target": "Cosette", "value": 2 },
+ { "source": "Mlle.Gillenormand", "target": "Valjean", "value": 2 },
+ { "source": "Mme.Pontmercy", "target": "Mlle.Gillenormand", "value": 1 },
+ { "source": "Mme.Pontmercy", "target": "Pontmercy", "value": 1 },
+ { "source": "Mlle.Vaubois", "target": "Mlle.Gillenormand", "value": 1 },
+ { "source": "Lt.Gillenormand", "target": "Mlle.Gillenormand", "value": 2 },
+ { "source": "Lt.Gillenormand", "target": "Gillenormand", "value": 1 },
+ { "source": "Lt.Gillenormand", "target": "Cosette", "value": 1 },
+ { "source": "Marius", "target": "Mlle.Gillenormand", "value": 6 },
+ { "source": "Marius", "target": "Gillenormand", "value": 12 },
+ { "source": "Marius", "target": "Pontmercy", "value": 1 },
+ { "source": "Marius", "target": "Lt.Gillenormand", "value": 1 },
+ { "source": "Marius", "target": "Cosette", "value": 21 },
+ { "source": "Marius", "target": "Valjean", "value": 19 },
+ { "source": "Marius", "target": "Tholomyes", "value": 1 },
+ { "source": "Marius", "target": "Thenardier", "value": 2 },
+ { "source": "Marius", "target": "Eponine", "value": 5 },
+ { "source": "Marius", "target": "Gavroche", "value": 4 },
+ { "source": "BaronessT", "target": "Gillenormand", "value": 1 },
+ { "source": "BaronessT", "target": "Marius", "value": 1 },
+ { "source": "Mabeuf", "target": "Marius", "value": 1 },
+ { "source": "Mabeuf", "target": "Eponine", "value": 1 },
+ { "source": "Mabeuf", "target": "Gavroche", "value": 1 },
+ { "source": "Enjolras", "target": "Marius", "value": 7 },
+ { "source": "Enjolras", "target": "Gavroche", "value": 7 },
+ { "source": "Enjolras", "target": "Javert", "value": 6 },
+ { "source": "Enjolras", "target": "Mabeuf", "value": 1 },
+ { "source": "Enjolras", "target": "Valjean", "value": 4 },
+ { "source": "Combeferre", "target": "Enjolras", "value": 15 },
+ { "source": "Combeferre", "target": "Marius", "value": 5 },
+ { "source": "Combeferre", "target": "Gavroche", "value": 6 },
+ { "source": "Combeferre", "target": "Mabeuf", "value": 2 },
+ { "source": "Prouvaire", "target": "Gavroche", "value": 1 },
+ { "source": "Prouvaire", "target": "Enjolras", "value": 4 },
+ { "source": "Prouvaire", "target": "Combeferre", "value": 2 },
+ { "source": "Feuilly", "target": "Gavroche", "value": 2 },
+ { "source": "Feuilly", "target": "Enjolras", "value": 6 },
+ { "source": "Feuilly", "target": "Prouvaire", "value": 2 },
+ { "source": "Feuilly", "target": "Combeferre", "value": 5 },
+ { "source": "Feuilly", "target": "Mabeuf", "value": 1 },
+ { "source": "Feuilly", "target": "Marius", "value": 1 },
+ { "source": "Courfeyrac", "target": "Marius", "value": 9 },
+ { "source": "Courfeyrac", "target": "Enjolras", "value": 17 },
+ { "source": "Courfeyrac", "target": "Combeferre", "value": 13 },
+ { "source": "Courfeyrac", "target": "Gavroche", "value": 7 },
+ { "source": "Courfeyrac", "target": "Mabeuf", "value": 2 },
+ { "source": "Courfeyrac", "target": "Eponine", "value": 1 },
+ { "source": "Courfeyrac", "target": "Feuilly", "value": 6 },
+ { "source": "Courfeyrac", "target": "Prouvaire", "value": 3 },
+ { "source": "Bahorel", "target": "Combeferre", "value": 5 },
+ { "source": "Bahorel", "target": "Gavroche", "value": 5 },
+ { "source": "Bahorel", "target": "Courfeyrac", "value": 6 },
+ { "source": "Bahorel", "target": "Mabeuf", "value": 2 },
+ { "source": "Bahorel", "target": "Enjolras", "value": 4 },
+ { "source": "Bahorel", "target": "Feuilly", "value": 3 },
+ { "source": "Bahorel", "target": "Prouvaire", "value": 2 },
+ { "source": "Bahorel", "target": "Marius", "value": 1 },
+ { "source": "Bossuet", "target": "Marius", "value": 5 },
+ { "source": "Bossuet", "target": "Courfeyrac", "value": 12 },
+ { "source": "Bossuet", "target": "Gavroche", "value": 5 },
+ { "source": "Bossuet", "target": "Bahorel", "value": 4 },
+ { "source": "Bossuet", "target": "Enjolras", "value": 10 },
+ { "source": "Bossuet", "target": "Feuilly", "value": 6 },
+ { "source": "Bossuet", "target": "Prouvaire", "value": 2 },
+ { "source": "Bossuet", "target": "Combeferre", "value": 9 },
+ { "source": "Bossuet", "target": "Mabeuf", "value": 1 },
+ { "source": "Bossuet", "target": "Valjean", "value": 1 },
+ { "source": "Joly", "target": "Bahorel", "value": 5 },
+ { "source": "Joly", "target": "Bossuet", "value": 7 },
+ { "source": "Joly", "target": "Gavroche", "value": 3 },
+ { "source": "Joly", "target": "Courfeyrac", "value": 5 },
+ { "source": "Joly", "target": "Enjolras", "value": 5 },
+ { "source": "Joly", "target": "Feuilly", "value": 5 },
+ { "source": "Joly", "target": "Prouvaire", "value": 2 },
+ { "source": "Joly", "target": "Combeferre", "value": 5 },
+ { "source": "Joly", "target": "Mabeuf", "value": 1 },
+ { "source": "Joly", "target": "Marius", "value": 2 },
+ { "source": "Grantaire", "target": "Bossuet", "value": 3 },
+ { "source": "Grantaire", "target": "Enjolras", "value": 3 },
+ { "source": "Grantaire", "target": "Combeferre", "value": 1 },
+ { "source": "Grantaire", "target": "Courfeyrac", "value": 2 },
+ { "source": "Grantaire", "target": "Joly", "value": 2 },
+ { "source": "Grantaire", "target": "Gavroche", "value": 1 },
+ { "source": "Grantaire", "target": "Bahorel", "value": 1 },
+ { "source": "Grantaire", "target": "Feuilly", "value": 1 },
+ { "source": "Grantaire", "target": "Prouvaire", "value": 1 },
+ { "source": "MotherPlutarch", "target": "Mabeuf", "value": 3 },
+ { "source": "Gueulemer", "target": "Thenardier", "value": 5 },
+ { "source": "Gueulemer", "target": "Valjean", "value": 1 },
+ { "source": "Gueulemer", "target": "Mme.Thenardier", "value": 1 },
+ { "source": "Gueulemer", "target": "Javert", "value": 1 },
+ { "source": "Gueulemer", "target": "Gavroche", "value": 1 },
+ { "source": "Gueulemer", "target": "Eponine", "value": 1 },
+ { "source": "Babet", "target": "Thenardier", "value": 6 },
+ { "source": "Babet", "target": "Gueulemer", "value": 6 },
+ { "source": "Babet", "target": "Valjean", "value": 1 },
+ { "source": "Babet", "target": "Mme.Thenardier", "value": 1 },
+ { "source": "Babet", "target": "Javert", "value": 2 },
+ { "source": "Babet", "target": "Gavroche", "value": 1 },
+ { "source": "Babet", "target": "Eponine", "value": 1 },
+ { "source": "Claquesous", "target": "Thenardier", "value": 4 },
+ { "source": "Claquesous", "target": "Babet", "value": 4 },
+ { "source": "Claquesous", "target": "Gueulemer", "value": 4 },
+ { "source": "Claquesous", "target": "Valjean", "value": 1 },
+ { "source": "Claquesous", "target": "Mme.Thenardier", "value": 1 },
+ { "source": "Claquesous", "target": "Javert", "value": 1 },
+ { "source": "Claquesous", "target": "Eponine", "value": 1 },
+ { "source": "Claquesous", "target": "Enjolras", "value": 1 },
+ { "source": "Montparnasse", "target": "Javert", "value": 1 },
+ { "source": "Montparnasse", "target": "Babet", "value": 2 },
+ { "source": "Montparnasse", "target": "Gueulemer", "value": 2 },
+ { "source": "Montparnasse", "target": "Claquesous", "value": 2 },
+ { "source": "Montparnasse", "target": "Valjean", "value": 1 },
+ { "source": "Montparnasse", "target": "Gavroche", "value": 1 },
+ { "source": "Montparnasse", "target": "Eponine", "value": 1 },
+ { "source": "Montparnasse", "target": "Thenardier", "value": 1 },
+ { "source": "Toussaint", "target": "Cosette", "value": 2 },
+ { "source": "Toussaint", "target": "Javert", "value": 1 },
+ { "source": "Toussaint", "target": "Valjean", "value": 1 },
+ { "source": "Child1", "target": "Gavroche", "value": 2 },
+ { "source": "Child2", "target": "Gavroche", "value": 2 },
+ { "source": "Child2", "target": "Child1", "value": 3 },
+ { "source": "Brujon", "target": "Babet", "value": 3 },
+ { "source": "Brujon", "target": "Gueulemer", "value": 3 },
+ { "source": "Brujon", "target": "Thenardier", "value": 3 },
+ { "source": "Brujon", "target": "Gavroche", "value": 1 },
+ { "source": "Brujon", "target": "Eponine", "value": 1 },
+ { "source": "Brujon", "target": "Claquesous", "value": 1 },
+ { "source": "Brujon", "target": "Montparnasse", "value": 1 },
+ { "source": "Mme.Hucheloup", "target": "Bossuet", "value": 1 },
+ { "source": "Mme.Hucheloup", "target": "Joly", "value": 1 },
+ { "source": "Mme.Hucheloup", "target": "Grantaire", "value": 1 },
+ { "source": "Mme.Hucheloup", "target": "Bahorel", "value": 1 },
+ { "source": "Mme.Hucheloup", "target": "Courfeyrac", "value": 1 },
+ { "source": "Mme.Hucheloup", "target": "Gavroche", "value": 1 },
+ { "source": "Mme.Hucheloup", "target": "Enjolras", "value": 1 }
+ ]
+ };
+ private svg;
+ private margin = 50;
+ private width = 750 - (this.margin * 2);
+ private height = 400 - (this.margin * 2);
+ private update: () => void;
+
+ private createGraph(): any {
+ const nodes = this.data.nodes.map(({ id, group }) => ({
+ id,
+ sourceLinks: [],
+ targetLinks: [],
+ group
+ }));
+
+ const nodeById = new Map(nodes.map(d => [d.id, d]));
+
+ const links = this.data.links.map(({ source, target, value }) => ({
+ source: nodeById.get(source),
+ target: nodeById.get(target),
+ value
+ }));
+
+ for (const link of links) {
+ const { source, target, value } = link;
+ source.sourceLinks.push(link);
+ target.targetLinks.push(link);
+ }
+
+ return { nodes, links };
+ }
+
+ private createChart(): any {
+ const margin = ({ top: 20, right: 20, bottom: 20, left: 100 });
+
+ function arc(d) {
+ const y1 = d.source.y;
+ const y2 = d.target.y;
+ const r = Math.abs(y2 - y1) / 2;
+ return `M${margin.left},${y1}A${r},${r} 0,0,${y1 < y2 ? 1 : 0} ${margin.left},${y2}`;
+ }
+
+ var graph = this.createGraph();
+ const color = d3.scaleOrdinal(graph.nodes.map(d => d.group).sort(d3.ascending), d3.schemeCategory10);
+ const step = 14;
+ const height = (this.data.nodes.length - 1) * step + margin.top + margin.bottom;
+ const y = d3.scalePoint(graph.nodes.map(d => d.id).sort(d3.ascending), [margin.top, height - margin.bottom]);
+
+ this.createSvg(height);
+
+ this.svg.append("style").text(`
+
+ .hover path {
+ stroke: #ccc;
+ }
+
+ .hover text {
+ fill: #ccc;
+ }
+
+ .hover g.primary text {
+ fill: black;
+ font-weight: bold;
+ }
+
+ .hover g.secondary text {
+ fill: #333;
+ }
+
+ .hover path.primary {
+ stroke: #333;
+ stroke-opacity: 1;
+ }
+
+ `);
+
+ const label = this.svg.append("g")
+ .attr("font-family", "sans-serif")
+ .attr("font-size", 10)
+ .attr("text-anchor", "end")
+ .selectAll("g")
+ .data(graph.nodes)
+ .join("g")
+ .attr("transform", d => `translate(${margin.left},${d.y = y(d.id)})`)
+ .call(g => g.append("text")
+ .attr("x", -6)
+ .attr("dy", "0.35em")
+ .attr("fill", d => d3.lab(color(d.group)).darker(2))
+ .text(d => d.id))
+ .call(g => g.append("circle")
+ .attr("r", 3)
+ .attr("fill", d => color(d.group)));
+
+ const path = this.svg.insert("g", "*")
+ .attr("fill", "none")
+ .attr("stroke-opacity", 0.6)
+ .attr("stroke-width", 1.5)
+ .selectAll("path")
+ .data(graph.links)
+ .join("path")
+ .attr("stroke", d => d.source.group === d.target.group ? color(d.source.group) : "#aaa")
+ .attr("d", arc);
+
+ const overlay = this.svg.append("g")
+ .attr("fill", "none")
+ .attr("pointer-events", "all")
+ .selectAll("rect")
+ .data(graph.nodes)
+ .join("rect")
+ .attr("width", margin.left + 40)
+ .attr("height", step)
+ .attr("y", d => y(d.id) - step / 2)
+ .on("mouseover", d => {
+ this.svg.classed("hover", true);
+ label.classed("primary", n => n === d);
+ label.classed("secondary", n => n.sourceLinks.some(l => l.target === d) || n.targetLinks.some(l => l.source === d));
+ path.classed("primary", l => l.source === d || l.target === d).filter(".primary").raise();
+ })
+ .on("mouseout", d => {
+ this.svg.classed("hover", false);
+ label.classed("primary", false);
+ label.classed("secondary", false);
+ path.classed("primary", false).order();
+ });
+
+ const orderFn = (a, b) => a.group - b.group || d3.ascending(a.id, b.id);
+
+ this.update = function() {
+ y.domain(graph.nodes.sort(orderFn).map(d => d.id));
+
+ const t = this.svg.transition()
+ .duration(750);
+
+ label.transition(t)
+ .delay((d, i) => i * 20)
+ .attrTween("transform", d => {
+ const i = d3.interpolateNumber(d.y, y(d.id));
+ return t => `translate(${margin.left},${d.y = i(t)})`;
+ });
+
+ path.transition(t)
+ .duration(750 + graph.nodes.length * 20)
+ .attrTween("d", d => () => arc(d));
+
+ overlay.transition(t)
+ .delay((d, i) => i * 20)
+ .attr("y", d => y(d.id) - step / 2);
+ }
+
+ //viewof order.addEventListener("input", update);
+ //invalidation.then(() => viewof order.removeEventListener("input", update));
+
+ return this.svg.node();
+ }
+
+ private createSvg(height): void {
+ this.svg = d3.select("figure#bar")
+ .append("svg")
+ .attr("height", height)
+ .attr("width", this.width + (this.margin * 2))
+ //.attr("height", this.height + (this.margin * 2))
+ //.append("g")
+ //.attr("transform", "translate(" + this.margin + "," + this.margin + ")");
+ }
+
+ private drawBars(data: any[]): void {
+ // Create the X-axis band scale
+ const x = d3.scaleBand()
+ .range([0, this.width])
+ .domain(data.map(d => d.Framework))
+ .padding(0.2);
+
+ // Draw the X-axis on the DOM
+ this.svg.append("g")
+ .attr("transform", "translate(0," + this.height + ")")
+ .call(d3.axisBottom(x))
+ .selectAll("text")
+ .attr("transform", "translate(-10,0)rotate(-45)")
+ .style("text-anchor", "end");
+
+ // Create the Y-axis band scale
+ const y = d3.scaleLinear()
+ .domain([0, 200000])
+ .range([this.height, 0]);
+
+ // Draw the Y-axis on the DOM
+ this.svg.append("g")
+ .call(d3.axisLeft(y));
+
+ // Create and fill the bars
+ this.svg.selectAll("bars")
+ .data(data)
+ .enter()
+ .append("rect")
+ .attr("x", d => x(d.Framework))
+ .attr("y", d => y(d.Stars))
+ .attr("width", x.bandwidth())
+ .attr("height", (d) => this.height - y(d.Stars))
+ .attr("fill", "#d04a35");
+ }
+
+ constructor() { }
+
+ ngOnInit(): void {
+ this.createChart();
+ this.update();
+ }
+
+}
diff --git a/src/app/objects/factions/factions-routing.module.ts b/src/app/objects/factions/factions-routing.module.ts
index dfb7a6ef..80659be1 100644
--- a/src/app/objects/factions/factions-routing.module.ts
+++ b/src/app/objects/factions/factions-routing.module.ts
@@ -4,9 +4,11 @@ import { FactionsGraphComponent } from './graph/factions.component';
import { ObjectsByFactionComponent } from './objects-by-faction/objects-by-faction.component';
import { RouterModule } from '@angular/router';
import { IndexComponent } from './index/index.component';
+import { D3GraphComponent } from './d3-graph/d3-graph.component';
const factionsRoutes = [
{ path: 'graph', component: FactionsGraphComponent, data: { title: "Factions Graph" } },
+ { path: 'graph/d3', component: D3GraphComponent, data: { title: "Factions Graph" } },
{ path: ':id', component: ObjectsByFactionComponent, data: { title: params => `Faction #${params['id']}` } },
{ path: '', component: IndexComponent, data: { title: "Factions" } }
];
diff --git a/src/app/objects/factions/factions.module.ts b/src/app/objects/factions/factions.module.ts
index 77e54a0e..59630582 100644
--- a/src/app/objects/factions/factions.module.ts
+++ b/src/app/objects/factions/factions.module.ts
@@ -7,6 +7,7 @@ import { FactionsRoutingModule } from './factions-routing.module';
import { UtilModule } from '../../util/util.module';
import { IndexComponent } from './index/index.component';
import { GuiModule } from '../../gui/gui.module';
+import { D3GraphComponent } from './d3-graph/d3-graph.component';
@NgModule({
@@ -14,6 +15,7 @@ import { GuiModule } from '../../gui/gui.module';
FactionsGraphComponent,
ObjectsByFactionComponent,
IndexComponent,
+ D3GraphComponent,
],
imports: [
CommonModule,
diff --git a/src/app/objects/factions/index/index.component.html b/src/app/objects/factions/index/index.component.html
index 2efaf364..3ceb0c0d 100644
--- a/src/app/objects/factions/index/index.component.html
+++ b/src/app/objects/factions/index/index.component.html
@@ -3,7 +3,7 @@
Factions
-Factions
+