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

    +

    Factions [Graph]