adding necessary files
9
ReactTool/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Mini VLAT Activity using REACT + Flask
|
||||
|
||||
This repository contains the following three major parts. Each directory has its own README on how to run the code.
|
||||
|
||||
## frontend
|
||||
This directory contains the (React) frontend of our web application which will be used for user studies.
|
||||
|
||||
## backend
|
||||
This directory contains the (Python Flask) backend of our our web application. Ultimately, the techniques we develope in preprocessing will be moved to this directory for deployment.
|
||||
24
ReactTool/backend/Pipfile
Normal file
@@ -0,0 +1,24 @@
|
||||
[[source]]
|
||||
url = "https://pypi.org/simple"
|
||||
verify_ssl = true
|
||||
name = "pypi"
|
||||
|
||||
[packages]
|
||||
flask = "*"
|
||||
numpy = "*"
|
||||
pandas = "*"
|
||||
python-dotenv = "*"
|
||||
scipy = "*"
|
||||
matplotlib = "*"
|
||||
gunicorn = "*"
|
||||
flask-mysql = "*"
|
||||
mysql-connector-python = "*"
|
||||
flask-session = "*"
|
||||
flask-cors = "*"
|
||||
redis = "*"
|
||||
werkzeug = "*"
|
||||
|
||||
[dev-packages]
|
||||
|
||||
[requires]
|
||||
python_version = "3.9"
|
||||
600
ReactTool/backend/Pipfile.lock
generated
Normal file
@@ -0,0 +1,600 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "7a95aefa579b9f23293ec73c8a9df5a29b8bc5d4042d26f7e2f5eb8ff110ae1c"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
"python_version": "3.9"
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"name": "pypi",
|
||||
"url": "https://pypi.org/simple",
|
||||
"verify_ssl": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"default": {
|
||||
"cachelib": {
|
||||
"hashes": [
|
||||
"sha256:0baa926a23924c04ae1354091478b15b3b24e6cf5931dd159452afda5f65babd",
|
||||
"sha256:6da323fdb16c9f53424a229132646a469b2d046e687fa353b92303910c99bc18"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.6.0"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
|
||||
"sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==8.0.3"
|
||||
},
|
||||
"cycler": {
|
||||
"hashes": [
|
||||
"sha256:3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3",
|
||||
"sha256:9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==0.11.0"
|
||||
},
|
||||
"deprecated": {
|
||||
"hashes": [
|
||||
"sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d",
|
||||
"sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.2.13"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2",
|
||||
"sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.0.2"
|
||||
},
|
||||
"flask-cors": {
|
||||
"hashes": [
|
||||
"sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438",
|
||||
"sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.0.10"
|
||||
},
|
||||
"flask-mysql": {
|
||||
"hashes": [
|
||||
"sha256:6d50e6560c88a48414dd63df790cb29ed927d41edfb21b572d6e7b530f15dfcd",
|
||||
"sha256:d05b5c4c87ecf8468633d5d623b94c99b02f3ad66f89797718c0e2c8ff425bd3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.5.2"
|
||||
},
|
||||
"flask-session": {
|
||||
"hashes": [
|
||||
"sha256:1e3f8a317005db72c831f85d884a5a9d23145f256c730d80b325a3150a22c3db",
|
||||
"sha256:c9ed54321fa8c4ca0132ffd3369582759eda7252fb4b3bee480e690d1ba41f46"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.4.0"
|
||||
},
|
||||
"fonttools": {
|
||||
"hashes": [
|
||||
"sha256:1933415e0fbdf068815cb1baaa1f159e17830215f7e8624e5731122761627557",
|
||||
"sha256:2b18a172120e32128a80efee04cff487d5d140fe7d817deb648b2eee023a40e4"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==4.29.1"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
"sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
|
||||
"sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==20.1.0"
|
||||
},
|
||||
"itsdangerous": {
|
||||
"hashes": [
|
||||
"sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
|
||||
"sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.1"
|
||||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8",
|
||||
"sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.3"
|
||||
},
|
||||
"kiwisolver": {
|
||||
"hashes": [
|
||||
"sha256:0007840186bacfaa0aba4466d5890334ea5938e0bb7e28078a0eb0e63b5b59d5",
|
||||
"sha256:19554bd8d54cf41139f376753af1a644b63c9ca93f8f72009d50a2080f870f77",
|
||||
"sha256:1d45d1c74f88b9f41062716c727f78f2a59a5476ecbe74956fafb423c5c87a76",
|
||||
"sha256:1d819553730d3c2724582124aee8a03c846ec4362ded1034c16fb3ef309264e6",
|
||||
"sha256:2210f28778c7d2ee13f3c2a20a3a22db889e75f4ec13a21072eabb5693801e84",
|
||||
"sha256:22521219ca739654a296eea6d4367703558fba16f98688bd8ce65abff36eaa84",
|
||||
"sha256:25405f88a37c5f5bcba01c6e350086d65e7465fd1caaf986333d2a045045a223",
|
||||
"sha256:2b65bd35f3e06a47b5c30ea99e0c2b88f72c6476eedaf8cfbc8e66adb5479dcf",
|
||||
"sha256:2ddb500a2808c100e72c075cbb00bf32e62763c82b6a882d403f01a119e3f402",
|
||||
"sha256:2f8f6c8f4f1cff93ca5058d6ec5f0efda922ecb3f4c5fb76181f327decff98b8",
|
||||
"sha256:30fa008c172355c7768159983a7270cb23838c4d7db73d6c0f6b60dde0d432c6",
|
||||
"sha256:3dbb3cea20b4af4f49f84cffaf45dd5f88e8594d18568e0225e6ad9dec0e7967",
|
||||
"sha256:4116ba9a58109ed5e4cb315bdcbff9838f3159d099ba5259c7c7fb77f8537492",
|
||||
"sha256:44e6adf67577dbdfa2d9f06db9fbc5639afefdb5bf2b4dfec25c3a7fbc619536",
|
||||
"sha256:5326ddfacbe51abf9469fe668944bc2e399181a2158cb5d45e1d40856b2a0589",
|
||||
"sha256:70adc3658138bc77a36ce769f5f183169bc0a2906a4f61f09673f7181255ac9b",
|
||||
"sha256:72be6ebb4e92520b9726d7146bc9c9b277513a57a38efcf66db0620aec0097e0",
|
||||
"sha256:7843b1624d6ccca403a610d1277f7c28ad184c5aa88a1750c1a999754e65b439",
|
||||
"sha256:7ba5a1041480c6e0a8b11a9544d53562abc2d19220bfa14133e0cdd9967e97af",
|
||||
"sha256:80efd202108c3a4150e042b269f7c78643420cc232a0a771743bb96b742f838f",
|
||||
"sha256:82f49c5a79d3839bc8f38cb5f4bfc87e15f04cbafa5fbd12fb32c941cb529cfb",
|
||||
"sha256:83d2c9db5dfc537d0171e32de160461230eb14663299b7e6d18ca6dca21e4977",
|
||||
"sha256:8d93a1095f83e908fc253f2fb569c2711414c0bfd451cab580466465b235b470",
|
||||
"sha256:8dc3d842fa41a33fe83d9f5c66c0cc1f28756530cd89944b63b072281e852031",
|
||||
"sha256:9661a04ca3c950a8ac8c47f53cbc0b530bce1b52f516a1e87b7736fec24bfff0",
|
||||
"sha256:a498bcd005e8a3fedd0022bb30ee0ad92728154a8798b703f394484452550507",
|
||||
"sha256:a7a4cf5bbdc861987a7745aed7a536c6405256853c94abc9f3287c3fa401b174",
|
||||
"sha256:b5074fb09429f2b7bc82b6fb4be8645dcbac14e592128beeff5461dcde0af09f",
|
||||
"sha256:b6a5431940f28b6de123de42f0eb47b84a073ee3c3345dc109ad550a3307dd28",
|
||||
"sha256:ba677bcaff9429fd1bf01648ad0901cea56c0d068df383d5f5856d88221fe75b",
|
||||
"sha256:bcadb05c3d4794eb9eee1dddf1c24215c92fb7b55a80beae7a60530a91060560",
|
||||
"sha256:bf7eb45d14fc036514c09554bf983f2a72323254912ed0c3c8e697b62c4c158f",
|
||||
"sha256:c358721aebd40c243894298f685a19eb0491a5c3e0b923b9f887ef1193ddf829",
|
||||
"sha256:c4550a359c5157aaf8507e6820d98682872b9100ce7607f8aa070b4b8af6c298",
|
||||
"sha256:c6572c2dab23c86a14e82c245473d45b4c515314f1f859e92608dcafbd2f19b8",
|
||||
"sha256:cba430db673c29376135e695c6e2501c44c256a81495da849e85d1793ee975ad",
|
||||
"sha256:dedc71c8eb9c5096037766390172c34fb86ef048b8e8958b4e484b9e505d66bc",
|
||||
"sha256:e6f5eb2f53fac7d408a45fbcdeda7224b1cfff64919d0f95473420a931347ae9",
|
||||
"sha256:ec2eba188c1906b05b9b49ae55aae4efd8150c61ba450e6721f64620c50b59eb",
|
||||
"sha256:ee040a7de8d295dbd261ef2d6d3192f13e2b08ec4a954de34a6fb8ff6422e24c",
|
||||
"sha256:eedd3b59190885d1ebdf6c5e0ca56828beb1949b4dfe6e5d0256a461429ac386",
|
||||
"sha256:f441422bb313ab25de7b3dbfd388e790eceb76ce01a18199ec4944b369017009",
|
||||
"sha256:f8eb7b6716f5b50e9c06207a14172cf2de201e41912ebe732846c02c830455b9",
|
||||
"sha256:fc4453705b81d03568d5b808ad8f09c77c47534f6ac2e72e733f9ca4714aa75c"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.3.2"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
|
||||
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
|
||||
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
|
||||
"sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194",
|
||||
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
|
||||
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
|
||||
"sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724",
|
||||
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
|
||||
"sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646",
|
||||
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
|
||||
"sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6",
|
||||
"sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a",
|
||||
"sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6",
|
||||
"sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad",
|
||||
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
|
||||
"sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38",
|
||||
"sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac",
|
||||
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
|
||||
"sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6",
|
||||
"sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047",
|
||||
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
|
||||
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
|
||||
"sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b",
|
||||
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
|
||||
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
|
||||
"sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a",
|
||||
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
|
||||
"sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1",
|
||||
"sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9",
|
||||
"sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864",
|
||||
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
|
||||
"sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee",
|
||||
"sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f",
|
||||
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
|
||||
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
|
||||
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
|
||||
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
|
||||
"sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b",
|
||||
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
|
||||
"sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86",
|
||||
"sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6",
|
||||
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
|
||||
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
|
||||
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
|
||||
"sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28",
|
||||
"sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e",
|
||||
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
|
||||
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
|
||||
"sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f",
|
||||
"sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d",
|
||||
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
|
||||
"sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
|
||||
"sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145",
|
||||
"sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
|
||||
"sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c",
|
||||
"sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1",
|
||||
"sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a",
|
||||
"sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207",
|
||||
"sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
|
||||
"sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53",
|
||||
"sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd",
|
||||
"sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134",
|
||||
"sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85",
|
||||
"sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9",
|
||||
"sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
|
||||
"sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
|
||||
"sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
|
||||
"sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
|
||||
"sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==2.0.1"
|
||||
},
|
||||
"matplotlib": {
|
||||
"hashes": [
|
||||
"sha256:14334b9902ec776461c4b8c6516e26b450f7ebe0b3ef8703bf5cdfbbaecf774a",
|
||||
"sha256:2252bfac85cec7af4a67e494bfccf9080bcba8a0299701eab075f48847cca907",
|
||||
"sha256:2e3484d8455af3fdb0424eae1789af61f6a79da0c80079125112fd5c1b604218",
|
||||
"sha256:34a1fc29f8f96e78ec57a5eff5e8d8b53d3298c3be6df61e7aa9efba26929522",
|
||||
"sha256:3e66497cd990b1a130e21919b004da2f1dc112132c01ac78011a90a0f9229778",
|
||||
"sha256:40e0d7df05e8efe60397c69b467fc8f87a2affeb4d562fe92b72ff8937a2b511",
|
||||
"sha256:456cc8334f6d1124e8ff856b42d2cc1c84335375a16448189999496549f7182b",
|
||||
"sha256:506b210cc6e66a0d1c2bb765d055f4f6bc2745070fb1129203b67e85bbfa5c18",
|
||||
"sha256:53273c5487d1c19c3bc03b9eb82adaf8456f243b97ed79d09dded747abaf1235",
|
||||
"sha256:577ed20ec9a18d6bdedb4616f5e9e957b4c08563a9f985563a31fd5b10564d2a",
|
||||
"sha256:6803299cbf4665eca14428d9e886de62e24f4223ac31ab9c5d6d5339a39782c7",
|
||||
"sha256:68fa30cec89b6139dc559ed6ef226c53fd80396da1919a1b5ef672c911aaa767",
|
||||
"sha256:6c094e4bfecd2fa7f9adffd03d8abceed7157c928c2976899de282f3600f0a3d",
|
||||
"sha256:778d398c4866d8e36ee3bf833779c940b5f57192fa0a549b3ad67bc4c822771b",
|
||||
"sha256:7a350ca685d9f594123f652ba796ee37219bf72c8e0fc4b471473d87121d6d34",
|
||||
"sha256:87900c67c0f1728e6db17c6809ec05c025c6624dcf96a8020326ea15378fe8e7",
|
||||
"sha256:8a77906dc2ef9b67407cec0bdbf08e3971141e535db888974a915be5e1e3efc6",
|
||||
"sha256:8e70ae6475cfd0fad3816dcbf6cac536dc6f100f7474be58d59fa306e6e768a4",
|
||||
"sha256:abf67e05a1b7f86583f6ebd01f69b693b9c535276f4e943292e444855870a1b8",
|
||||
"sha256:b04fc29bcef04d4e2d626af28d9d892be6aba94856cb46ed52bcb219ceac8943",
|
||||
"sha256:b19a761b948e939a9e20173aaae76070025f0024fc8f7ba08bef22a5c8573afc",
|
||||
"sha256:b2e9810e09c3a47b73ce9cab5a72243a1258f61e7900969097a817232246ce1c",
|
||||
"sha256:b71f3a7ca935fc759f2aed7cec06cfe10bc3100fadb5dbd9c435b04e557971e1",
|
||||
"sha256:b8a4fb2a0c5afbe9604f8a91d7d0f27b1832c3e0b5e365f95a13015822b4cd65",
|
||||
"sha256:bb1c613908f11bac270bc7494d68b1ef6e7c224b7a4204d5dacf3522a41e2bc3",
|
||||
"sha256:d24e5bb8028541ce25e59390122f5e48c8506b7e35587e5135efcb6471b4ac6c",
|
||||
"sha256:d70a32ee1f8b55eed3fd4e892f0286df8cccc7e0475c11d33b5d0a148f5c7599",
|
||||
"sha256:e293b16cf303fe82995e41700d172a58a15efc5331125d08246b520843ef21ee",
|
||||
"sha256:e2f28a07b4f82abb40267864ad7b3a4ed76f1b1663e81c7efc84a9b9248f672f",
|
||||
"sha256:e3520a274a0e054e919f5b3279ee5dbccf5311833819ccf3399dab7c83e90a25",
|
||||
"sha256:e3b6f3fd0d8ca37861c31e9a7cab71a0ef14c639b4c95654ea1dd153158bf0df",
|
||||
"sha256:e486f60db0cd1c8d68464d9484fd2a94011c1ac8593d765d0211f9daba2bd535",
|
||||
"sha256:e8c87cdaf06fd7b2477f68909838ff4176f105064a72ca9d24d3f2a29f73d393",
|
||||
"sha256:edf5e4e1d5fb22c18820e8586fb867455de3b109c309cb4fce3aaed85d9468d1",
|
||||
"sha256:fe8d40c434a8e2c68d64c6d6a04e77f21791a93ff6afe0dce169597c110d3079"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==3.5.1"
|
||||
},
|
||||
"mysql-connector-python": {
|
||||
"hashes": [
|
||||
"sha256:04d75ec7c181e7907df3d40c2a573063f25ecfc5a95a7a90374861c02ce738a9",
|
||||
"sha256:47f059bc2a7378acd56ac7a60b0526a2ba95d96b696a875b5b233a0feae30980",
|
||||
"sha256:4d126ce5e03675d926a9e49ce1638d06af43ca7bac2b502d93373dc9425d386f",
|
||||
"sha256:50c87ff50762f4a0cc0816365dde0e7de763949e125488b8e872de6471e0e427",
|
||||
"sha256:687071dc9e51892d0861bbcbcbd48e0f3579e3155f2a0ec310198704137c775a",
|
||||
"sha256:73c5149b33401610e28589d1fc669cba11d3b16215a8f6a75f63ece1f3af5f88",
|
||||
"sha256:77ec293e265d01db1896a8e63a16b3d5c848a885cf76c77148adfed8453846e8",
|
||||
"sha256:78bb1abb57bbb85263d65a240a901195e3de0e0992f25e42c48af0869079bb74",
|
||||
"sha256:7d518491d6d51b186b3182b3698b1560d9bd80675c055163359d0aeea0001de1",
|
||||
"sha256:8d8dd02e0e6bb7262156a836c3e83582d1a1a1ebb9d72e777a46813709404601",
|
||||
"sha256:91be638d1b084835edf7aa426d85228174611a1cd6f016ca0f6d4339ac3d9d7b",
|
||||
"sha256:aaec9d13fc0177e421a3c4392f0eaf86347b825949d5dfc202d535cdb1e07f04",
|
||||
"sha256:b3a747c5efd6de7b76686ab93834186e2276a62684600dbede615537040436ca",
|
||||
"sha256:b4c5ce835078555b6640921cae036daad46884dd21027f43c742fb505221e4e6",
|
||||
"sha256:bb317b179bfbb3e86c771bb2b34794188a2d2b010cdaa1b4d1b5ea0961d0812c",
|
||||
"sha256:bd89598b173aa0fc525b59fff6e3598ff3cabad4260a3bb49cf420eac10d3b3b",
|
||||
"sha256:bdb4f187f737316d1c403085b2fb7c91717268d052ecbfc86066cef59f6d72a4",
|
||||
"sha256:c76d771fdce1314b07619efff184ec03f56abef6b4ccdc686d3a995f5b225fec",
|
||||
"sha256:d559f69e8b58ac248e37d30e5676718adf69eeff56ed8a7c03f064d74af68f99",
|
||||
"sha256:e008127430c8dc66bb1b6d6c7a17498ec57ffa81188fc1f8c9f764363c01d12e",
|
||||
"sha256:f5da43c77d409c8135132f5b5aee9ac91c2e97c3f87352e1b3017438a9cb9b82"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==8.0.28"
|
||||
},
|
||||
"numpy": {
|
||||
"hashes": [
|
||||
"sha256:03ae5850619abb34a879d5f2d4bb4dcd025d6d8fb72f5e461dae84edccfe129f",
|
||||
"sha256:076aee5a3763d41da6bef9565fdf3cb987606f567cd8b104aded2b38b7b47abf",
|
||||
"sha256:0b536b6840e84c1c6a410f3a5aa727821e6108f3454d81a5cd5900999ef04f89",
|
||||
"sha256:15efb7b93806d438e3bc590ca8ef2f953b0ce4f86f337ef4559d31ec6cf9d7dd",
|
||||
"sha256:168259b1b184aa83a514f307352c25c56af111c269ffc109d9704e81f72e764b",
|
||||
"sha256:2638389562bda1635b564490d76713695ff497242a83d9b684d27bb4a6cc9d7a",
|
||||
"sha256:3556c5550de40027d3121ebbb170f61bbe19eb639c7ad0c7b482cd9b560cd23b",
|
||||
"sha256:4a176959b6e7e00b5a0d6f549a479f869829bfd8150282c590deee6d099bbb6e",
|
||||
"sha256:515a8b6edbb904594685da6e176ac9fbea8f73a5ebae947281de6613e27f1956",
|
||||
"sha256:55535c7c2f61e2b2fc817c5cbe1af7cb907c7f011e46ae0a52caa4be1f19afe2",
|
||||
"sha256:59153979d60f5bfe9e4c00e401e24dfe0469ef8da6d68247439d3278f30a180f",
|
||||
"sha256:60cb8e5933193a3cc2912ee29ca331e9c15b2da034f76159b7abc520b3d1233a",
|
||||
"sha256:6767ad399e9327bfdbaa40871be4254d1995f4a3ca3806127f10cec778bd9896",
|
||||
"sha256:76a4f9bce0278becc2da7da3b8ef854bed41a991f4226911a24a9711baad672c",
|
||||
"sha256:8cf33634b60c9cef346663a222d9841d3bbbc0a2f00221d6bcfd0d993d5543f6",
|
||||
"sha256:94dd11d9f13ea1be17bac39c1942f527cbf7065f94953cf62dfe805653da2f8f",
|
||||
"sha256:aafa46b5a39a27aca566198d3312fb3bde95ce9677085efd02c86f7ef6be4ec7",
|
||||
"sha256:badca914580eb46385e7f7e4e426fea6de0a37b9e06bec252e481ae7ec287082",
|
||||
"sha256:d76a26c5118c4d96e264acc9e3242d72e1a2b92e739807b3b69d8d47684b6677"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.22.2"
|
||||
},
|
||||
"packaging": {
|
||||
"hashes": [
|
||||
"sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
|
||||
"sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==21.3"
|
||||
},
|
||||
"pandas": {
|
||||
"hashes": [
|
||||
"sha256:0f19504f2783526fb5b4de675ea69d68974e21c1624f4b92295d057a31d5ec5f",
|
||||
"sha256:156aac90dd7b303bf0b91bae96c0503212777f86c731e41929c571125d26c8e9",
|
||||
"sha256:1d59c958d6b8f96fdf850c7821571782168d5acfe75ccf78cd8d1ac15fb921df",
|
||||
"sha256:1f3b74335390dda49f5d5089fab71958812bf56f42aa27663ee4c16d19f4f1c5",
|
||||
"sha256:23c04dab11f3c6359cfa7afa83d3d054a8f8c283d773451184d98119ef54da97",
|
||||
"sha256:2dad075089e17a72391de33021ad93720aff258c3c4b68c78e1cafce7e447045",
|
||||
"sha256:46a18572f3e1cb75db59d9461940e9ba7ee38967fa48dd58f4139197f6e32280",
|
||||
"sha256:4a8d5a200f8685e7ea562b2f022c77ab7cb82c1ca5b240e6965faa6f84e5c1e9",
|
||||
"sha256:51e5da3802aaee1aa4254108ffaf1129a15fb3810b7ce8da1ec217c655b418f5",
|
||||
"sha256:5229c95db3a907451dacebc551492db6f7d01743e49bbc862f4a6010c227d187",
|
||||
"sha256:5280d057ddae06fe4a3cd6aa79040b8c205cd6dd21743004cf8635f39ed01712",
|
||||
"sha256:55ec0e192eefa26d823fc25a1f213d6c304a3592915f368e360652994cdb8d9a",
|
||||
"sha256:73f7da2ccc38cc988b74e5400b430b7905db5f2c413ff215506bea034eaf832d",
|
||||
"sha256:784cca3f69cfd7f6bd7c7fdb44f2bbab17e6de55725e9ff36d6f382510dfefb5",
|
||||
"sha256:b5af258c7b090cca7b742cf2bd67ad1919aa9e4e681007366c9edad2d6a3d42b",
|
||||
"sha256:cdd76254c7f0a1583bd4e4781fb450d0ebf392e10d3f12e92c95575942e37df5",
|
||||
"sha256:de62cf699122dcef175988f0714678e59c453dc234c5b47b7136bfd7641e3c8c",
|
||||
"sha256:de8f8999864399529e8514a2e6bfe00fd161f0a667903655552ed12e583ae3cb",
|
||||
"sha256:f045bb5c6bfaba536089573bf97d6b8ccc7159d951fe63904c395a5e486fbe14",
|
||||
"sha256:f103a5cdcd66cb18882ccdc18a130c31c3cfe3529732e7f10a8ab3559164819c",
|
||||
"sha256:fe454180ad31bbbe1e5d111b44443258730467f035e26b4e354655ab59405871"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.4.0"
|
||||
},
|
||||
"pillow": {
|
||||
"hashes": [
|
||||
"sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97",
|
||||
"sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049",
|
||||
"sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c",
|
||||
"sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae",
|
||||
"sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28",
|
||||
"sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030",
|
||||
"sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56",
|
||||
"sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976",
|
||||
"sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e",
|
||||
"sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e",
|
||||
"sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f",
|
||||
"sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b",
|
||||
"sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a",
|
||||
"sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e",
|
||||
"sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa",
|
||||
"sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7",
|
||||
"sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00",
|
||||
"sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838",
|
||||
"sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360",
|
||||
"sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b",
|
||||
"sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a",
|
||||
"sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd",
|
||||
"sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4",
|
||||
"sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70",
|
||||
"sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204",
|
||||
"sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc",
|
||||
"sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b",
|
||||
"sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669",
|
||||
"sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7",
|
||||
"sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e",
|
||||
"sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c",
|
||||
"sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092",
|
||||
"sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c",
|
||||
"sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5",
|
||||
"sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==9.0.1"
|
||||
},
|
||||
"protobuf": {
|
||||
"hashes": [
|
||||
"sha256:072fbc78d705d3edc7ccac58a62c4c8e0cec856987da7df8aca86e647be4e35c",
|
||||
"sha256:09297b7972da685ce269ec52af761743714996b4381c085205914c41fcab59fb",
|
||||
"sha256:16f519de1313f1b7139ad70772e7db515b1420d208cb16c6d7858ea989fc64a9",
|
||||
"sha256:1c91ef4110fdd2c590effb5dca8fdbdcb3bf563eece99287019c4204f53d81a4",
|
||||
"sha256:3112b58aac3bac9c8be2b60a9daf6b558ca3f7681c130dcdd788ade7c9ffbdca",
|
||||
"sha256:36cecbabbda242915529b8ff364f2263cd4de7c46bbe361418b5ed859677ba58",
|
||||
"sha256:4276cdec4447bd5015453e41bdc0c0c1234eda08420b7c9a18b8d647add51e4b",
|
||||
"sha256:435bb78b37fc386f9275a7035fe4fb1364484e38980d0dd91bc834a02c5ec909",
|
||||
"sha256:48ed3877fa43e22bcacc852ca76d4775741f9709dd9575881a373bd3e85e54b2",
|
||||
"sha256:54a1473077f3b616779ce31f477351a45b4fef8c9fd7892d6d87e287a38df368",
|
||||
"sha256:69da7d39e39942bd52848438462674c463e23963a1fdaa84d88df7fbd7e749b2",
|
||||
"sha256:6cbc312be5e71869d9d5ea25147cdf652a6781cf4d906497ca7690b7b9b5df13",
|
||||
"sha256:7bb03bc2873a2842e5ebb4801f5c7ff1bfbdf426f85d0172f7644fcda0671ae0",
|
||||
"sha256:7ca7da9c339ca8890d66958f5462beabd611eca6c958691a8fe6eccbd1eb0c6e",
|
||||
"sha256:835a9c949dc193953c319603b2961c5c8f4327957fe23d914ca80d982665e8ee",
|
||||
"sha256:84123274d982b9e248a143dadd1b9815049f4477dc783bf84efe6250eb4b836a",
|
||||
"sha256:8961c3a78ebfcd000920c9060a262f082f29838682b1f7201889300c1fbe0616",
|
||||
"sha256:96bd766831596d6014ca88d86dc8fe0fb2e428c0b02432fd9db3943202bf8c5e",
|
||||
"sha256:9df0c10adf3e83015ced42a9a7bd64e13d06c4cf45c340d2c63020ea04499d0a",
|
||||
"sha256:b38057450a0c566cbd04890a40edf916db890f2818e8682221611d78dc32ae26",
|
||||
"sha256:bd95d1dfb9c4f4563e6093a9aa19d9c186bf98fa54da5252531cc0d3a07977e7",
|
||||
"sha256:c1068287025f8ea025103e37d62ffd63fec8e9e636246b89c341aeda8a67c934",
|
||||
"sha256:c438268eebb8cf039552897d78f402d734a404f1360592fef55297285f7f953f",
|
||||
"sha256:cdc076c03381f5c1d9bb1abdcc5503d9ca8b53cf0a9d31a9f6754ec9e6c8af0f",
|
||||
"sha256:f358aa33e03b7a84e0d91270a4d4d8f5df6921abe99a377828839e8ed0c04e07",
|
||||
"sha256:f51d5a9f137f7a2cec2d326a74b6e3fc79d635d69ffe1b036d39fc7d75430d37"
|
||||
],
|
||||
"markers": "python_version >= '3.5'",
|
||||
"version": "==3.19.4"
|
||||
},
|
||||
"pymysql": {
|
||||
"hashes": [
|
||||
"sha256:41fc3a0c5013d5f039639442321185532e3e2c8924687abe6537de157d403641",
|
||||
"sha256:816927a350f38d56072aeca5dfb10221fe1dc653745853d30a216637f5d7ad36"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==1.0.2"
|
||||
},
|
||||
"pyparsing": {
|
||||
"hashes": [
|
||||
"sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea",
|
||||
"sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"
|
||||
],
|
||||
"markers": "python_version >= '3.6'",
|
||||
"version": "==3.0.7"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
|
||||
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==2.8.2"
|
||||
},
|
||||
"python-dotenv": {
|
||||
"hashes": [
|
||||
"sha256:32b2bdc1873fd3a3c346da1c6db83d0053c3c62f28f1f38516070c4c8971b1d3",
|
||||
"sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.19.2"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c",
|
||||
"sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"
|
||||
],
|
||||
"version": "==2021.3"
|
||||
},
|
||||
"redis": {
|
||||
"hashes": [
|
||||
"sha256:bf86397be532fc0a888d5976a5313a3a70d8f912d52bc0c09bffda4b8425a1d4",
|
||||
"sha256:f13eea4254e302485add677cadedaf1305c1b3a4e07535e23b7b239798ce9301"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==4.1.2"
|
||||
},
|
||||
"scipy": {
|
||||
"hashes": [
|
||||
"sha256:011d4386b53b933142f58a652aa0f149c9b9242abd4f900b9f4ea5fbafc86b89",
|
||||
"sha256:16e09ef68b352d73befa8bcaf3ebe25d3941fe1a58c82909d5589856e6bc8174",
|
||||
"sha256:31d4f2d6b724bc9a98e527b5849b8a7e589bf1ea630c33aa563eda912c9ff0bd",
|
||||
"sha256:38aa39b6724cb65271e469013aeb6f2ce66fd44f093e241c28a9c6bc64fd79ed",
|
||||
"sha256:3d573228c10a3a8c32b9037be982e6440e411b443a6267b067cac72f690b8d56",
|
||||
"sha256:3d9dd6c8b93a22bf9a3a52d1327aca7e092b1299fb3afc4f89e8eba381be7b59",
|
||||
"sha256:559a8a4c03a5ba9fe3232f39ed24f86457e4f3f6c0abbeae1fb945029f092720",
|
||||
"sha256:5e73343c5e0d413c1f937302b2e04fb07872f5843041bcfd50699aef6e95e399",
|
||||
"sha256:723b9f878095ed994756fa4ee3060c450e2db0139c5ba248ee3f9628bd64e735",
|
||||
"sha256:87b01c7d5761e8a266a0fbdb9d88dcba0910d63c1c671bdb4d99d29f469e9e03",
|
||||
"sha256:8f4d059a97b29c91afad46b1737274cb282357a305a80bdd9e8adf3b0ca6a3f0",
|
||||
"sha256:92b2c2af4183ed09afb595709a8ef5783b2baf7f41e26ece24e1329c109691a7",
|
||||
"sha256:937d28722f13302febde29847bbe554b89073fbb924a30475e5ed7b028898b5f",
|
||||
"sha256:a279e27c7f4566ef18bab1b1e2c37d168e365080974758d107e7d237d3f0f484",
|
||||
"sha256:ad5be4039147c808e64f99c0e8a9641eb5d2fa079ff5894dcd8240e94e347af4",
|
||||
"sha256:ae3e327da323d82e918e593460e23babdce40d7ab21490ddf9fc06dec6b91a18",
|
||||
"sha256:bb7088e89cd751acf66195d2f00cf009a1ea113f3019664032d9075b1e727b6c",
|
||||
"sha256:c17a1878d00a5dd2797ccd73623ceca9d02375328f6218ee6d921e1325e61aff",
|
||||
"sha256:c2bae431d127bf0b1da81fc24e4bba0a84d058e3a96b9dd6475dfcb3c5e8761e",
|
||||
"sha256:de2e80ee1d925984c2504812a310841c241791c5279352be4707cdcd7c255039",
|
||||
"sha256:e6f0cd9c0bd374ef834ee1e0f0999678d49dcc400ea6209113d81528958f97c7",
|
||||
"sha256:f3720d0124aced49f6f2198a6900304411dbbeed12f56951d7c66ebef05e3df6",
|
||||
"sha256:f4a6d3b9f9797eb2d43938ac2c5d96d02aed17ef170c8b38f11798717523ddba"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.8.0"
|
||||
},
|
||||
"setuptools": {
|
||||
"hashes": [
|
||||
"sha256:4f783948909b28124388eef286572e9e69c228b6866d44ac7475bd82e94b6503",
|
||||
"sha256:5d7a302d3c3ae24d3bbaaecf5c4544056b2dd44b3e6690014dc096d64f12d672"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==60.8.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
|
||||
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||
"version": "==1.16.0"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f",
|
||||
"sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.0.2"
|
||||
},
|
||||
"wrapt": {
|
||||
"hashes": [
|
||||
"sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179",
|
||||
"sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096",
|
||||
"sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374",
|
||||
"sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df",
|
||||
"sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185",
|
||||
"sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785",
|
||||
"sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7",
|
||||
"sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909",
|
||||
"sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918",
|
||||
"sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33",
|
||||
"sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068",
|
||||
"sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829",
|
||||
"sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af",
|
||||
"sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79",
|
||||
"sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce",
|
||||
"sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc",
|
||||
"sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36",
|
||||
"sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade",
|
||||
"sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca",
|
||||
"sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32",
|
||||
"sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125",
|
||||
"sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e",
|
||||
"sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709",
|
||||
"sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f",
|
||||
"sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b",
|
||||
"sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb",
|
||||
"sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb",
|
||||
"sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489",
|
||||
"sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640",
|
||||
"sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb",
|
||||
"sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851",
|
||||
"sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d",
|
||||
"sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44",
|
||||
"sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13",
|
||||
"sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2",
|
||||
"sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb",
|
||||
"sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b",
|
||||
"sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9",
|
||||
"sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755",
|
||||
"sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c",
|
||||
"sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a",
|
||||
"sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf",
|
||||
"sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3",
|
||||
"sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229",
|
||||
"sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e",
|
||||
"sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de",
|
||||
"sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554",
|
||||
"sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10",
|
||||
"sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80",
|
||||
"sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056",
|
||||
"sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea"
|
||||
],
|
||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||
"version": "==1.13.3"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
}
|
||||
8
ReactTool/backend/README.md
Executable file
@@ -0,0 +1,8 @@
|
||||
In order to run the frontend, execute the following commands
|
||||
(assuming you have `pipenv` installed already):
|
||||
```
|
||||
cd backend
|
||||
pipenv install
|
||||
pipenv shell
|
||||
flask run
|
||||
```
|
||||
BIN
ReactTool/backend/__pycache__/app.cpython-39.pyc
Normal file
BIN
ReactTool/backend/__pycache__/db_conf.cpython-39.pyc
Normal file
137
ReactTool/backend/app.py
Executable file
@@ -0,0 +1,137 @@
|
||||
import sys
|
||||
import math
|
||||
import time
|
||||
import os
|
||||
from flask import Flask, request, jsonify
|
||||
from flask.globals import session
|
||||
#from flaskext.mysql import MySQL
|
||||
import json
|
||||
import random
|
||||
import datetime
|
||||
import secrets
|
||||
#import numpy as np
|
||||
import pandas as pd
|
||||
import db_conf
|
||||
from flask import send_file
|
||||
#from flask_mail import Mail, Message
|
||||
#import firebase_admin
|
||||
#from firebase_admin import credentials, firestore, initialize_app, firebase
|
||||
|
||||
app = Flask(__name__, static_folder='../frontend/build', static_url_path='/')
|
||||
app.config['MYSQL_DATABASE_HOST'] = db_conf.host
|
||||
app.config['MYSQL_DATABASE_USER'] = db_conf.user
|
||||
app.config['MYSQL_DATABASE_PASSWORD'] = db_conf.password
|
||||
app.config['MYSQL_DATABASE_DB'] = db_conf.db
|
||||
db_table_prefix = 'miniVlat'
|
||||
#mail = Mail(app)
|
||||
|
||||
# app.config['MAIL_SERVER'] = 'smtp.gmail.com'
|
||||
# app.config['MAIL_PORT'] = 465
|
||||
# app.config['MAIL_USERNAME'] = 'minivlat@gmail.com'
|
||||
# app.config['MAIL_PASSWORD'] = "minivlat123"
|
||||
# app.config['MAIL_USE_TLS'] = False
|
||||
# app.config['MAIL_USE_SSL'] = True
|
||||
#mail = Mail(app)
|
||||
|
||||
#mysql = MySQL()
|
||||
# mysql.init_app(app)
|
||||
|
||||
global_session = {}
|
||||
|
||||
#cred = credentials.Certificate("securekey.json")
|
||||
#default_app = initialize_app(cred)
|
||||
#db = firestore.client()
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
|
||||
|
||||
print('ready')
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return app.send_static_file('index.html')
|
||||
|
||||
|
||||
@app.route('/get_time')
|
||||
def get_time():
|
||||
return jsonify({'time': time.time()})
|
||||
|
||||
|
||||
@app.route('/new_session_id', methods=['GET', 'POST'])
|
||||
def get_new_session_id():
|
||||
"""
|
||||
Returns a new session ID and sets up the session.
|
||||
"""
|
||||
data = request.json
|
||||
print(data)
|
||||
|
||||
# session id
|
||||
id = secrets.token_urlsafe(16)
|
||||
global_session[id] = {
|
||||
}
|
||||
|
||||
# insert session into database
|
||||
'''
|
||||
conn = mysql.connect()
|
||||
cur = conn.cursor()
|
||||
sql_statement = f"insert into {db_table_prefix}_participants (id, data_condition, policy_condition, presentation_condition, tutorial_loaded_client_time, tutorial_loaded) values (" + ", ".join(
|
||||
[f"\"{str(item)}\"" for item in [id, data_condition, policy_condition, presentation_condition, tutorial_loaded_client_time, datetime.datetime.today()]]) + ")"
|
||||
cur.execute(sql_statement)
|
||||
conn.commit()
|
||||
cur.fetchall()
|
||||
conn.close()
|
||||
'''
|
||||
|
||||
print('%d active users' % len(global_session.keys()))
|
||||
print(global_session.keys())
|
||||
|
||||
return jsonify({'new_id': id})
|
||||
|
||||
|
||||
@app.route('/record_responses_to_db', methods=['POST'])
|
||||
def record_responses_to_db():
|
||||
data = request.json
|
||||
session_id = data['session_id']
|
||||
#fname = str(session_id)+'.txt'
|
||||
#fname = './surveys/quiz/' + fname
|
||||
# with open(fname, 'w+') as test:
|
||||
# test.write(json.dumps(data) + "\n")
|
||||
#res = firebase.post(data_send)
|
||||
# data_send = json.dumps(data)
|
||||
# msg = Message("Quiz Response for " + str(session_id),sender='minivlat@gmail.com', recipients=['minivlat@gmail.com'])
|
||||
# msg.body = data_send
|
||||
# mail.send(msg)
|
||||
fname = str(session_id)+'.txt'
|
||||
fname = './surveys/quiz/' + fname
|
||||
with open(fname, 'w+') as test:
|
||||
test.write(json.dumps(data) + "\n")
|
||||
|
||||
print('TODO: Record quiz responses into a file or DB')
|
||||
print('Collected quiz data: ', data)
|
||||
return {'response': "json post succeeded"}
|
||||
|
||||
|
||||
# @app.route('/record_survey_to_db', methods=['POST'])
|
||||
# def record_survey_to_db():
|
||||
# data = request.json
|
||||
# session_id = data['session_id']
|
||||
|
||||
# #fname = str(session_id)+'.txt'
|
||||
# #fname = './surveys/demographicResponses/' + fname
|
||||
# # with open(fname, 'w+') as test2:
|
||||
# # test2.write(json.dumps(data) + "\n")
|
||||
# #res = firebase.post(data_send)
|
||||
# # data_send = json.dumps(data)
|
||||
# # msg = Message("Demographic Response for " + str(session_id),sender='minivlat@gmail.com', recipients=['minivlat@gmail.com'])
|
||||
# # msg.body = data_send
|
||||
# # mail.send(msg)
|
||||
# fname = str(session_id) + '.txt'
|
||||
# fname = './surveys/demographicResponses/' + fname
|
||||
# with open(fname, 'w+') as test2:
|
||||
# test2.write(json.dumps(data) + "\n")
|
||||
|
||||
# print('TODO: Record survey responses into a file or DB')
|
||||
# print('Collected survey data: ', data)
|
||||
# return {'response': "json post succeeded"}
|
||||
9
ReactTool/backend/db_conf.py
Executable file
@@ -0,0 +1,9 @@
|
||||
#host = 'webdb.engr.wustl.edu'
|
||||
#user = 'vstool'
|
||||
#password = 'VSt00L%%s'
|
||||
#db = 'visualdata_tool'
|
||||
|
||||
host = 'localhost'
|
||||
user = 'root'
|
||||
password = 'guest123'
|
||||
db = 'mvlat'
|
||||
23
ReactTool/frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
70
ReactTool/frontend/README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Getting Started with Create React App
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `yarn start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.\
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `yarn test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `yarn build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `yarn eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||
|
||||
### `yarn build` fails to minify
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
||||
36847
ReactTool/frontend/package-lock.json
generated
Normal file
62
ReactTool/frontend/package.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"homepage": "./",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.7.1",
|
||||
"@emotion/styled": "^11.6.0",
|
||||
"@mui/material": "^5.4.0",
|
||||
"@popperjs/core": "^2.11.2",
|
||||
"@ramonak/react-progress-bar": "^4.1.0",
|
||||
"@react-pdf/renderer": "^2.1.1",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
"@testing-library/react": "^11.1.0",
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"bootstrap": "^5.1.3",
|
||||
"d3": "^7.1.1",
|
||||
"pdf-viewer-reactjs": "^2.2.3",
|
||||
"react": "^17.0.2",
|
||||
"react-bootstrap": "^2.0.2",
|
||||
"react-confetti": "^6.0.1",
|
||||
"react-copy-to-clipboard": "^5.0.4",
|
||||
"react-countdown": "^2.3.2",
|
||||
"react-countdown-clock": "^2.10.0",
|
||||
"react-countdown-clock-timer": "^2.1.2",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-likert-scale": "^4.1.2",
|
||||
"react-pdf": "^5.7.1",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-scripts": "4.0.3",
|
||||
"react-share": "^4.4.0",
|
||||
"react-svg-timer": "^2.1.1",
|
||||
"topojson": "^3.0.2",
|
||||
"web-vitals": "^1.0.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"new_build": "react-scripts --openssl-legacy-provider build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"proxy": "http://localhost:5000"
|
||||
}
|
||||
BIN
ReactTool/frontend/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
43
ReactTool/frontend/public/index.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>Mini-VLAT</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
BIN
ReactTool/frontend/public/logo192.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
ReactTool/frontend/public/logo512.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
25
ReactTool/frontend/public/manifest.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
3
ReactTool/frontend/public/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
1082
ReactTool/frontend/src/App.css
Normal file
49
ReactTool/frontend/src/App.js
Normal file
@@ -0,0 +1,49 @@
|
||||
import React, { Component } from 'react';
|
||||
import { HashRouter as BrowserRouter, Route, Switch } from 'react-router-dom';
|
||||
import './App.css';
|
||||
import ThankYou from "./pages/thank_you";
|
||||
import Intro from "./pages/introduction";
|
||||
import Tutorial from "./pages/tutorial";
|
||||
import VisQuiz from "./pages/visualization_quiz";
|
||||
|
||||
class App extends Component {
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onUnload(e) {
|
||||
|
||||
}
|
||||
|
||||
componentDidMount(params) {
|
||||
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
//window.removeEventListener("beforeunload", this.onUnload);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<div className="App">
|
||||
<BrowserRouter>
|
||||
<Switch>
|
||||
<Route exact path="/" component={Intro} />
|
||||
<Route exact path={"/tutorial"} component={Tutorial} />
|
||||
<Route exact path="/experiment" component={VisQuiz} />
|
||||
<Route exact path='/thank_you' component={ThankYou} />
|
||||
</Switch>
|
||||
</BrowserRouter>
|
||||
</div>
|
||||
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
||||
8
ReactTool/frontend/src/App.test.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
||||
174
ReactTool/frontend/src/components/areaChart-mini.js
Normal file
@@ -0,0 +1,174 @@
|
||||
//Using monthly coffee price dataset
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/AreaChart-2.csv';
|
||||
import img10 from '../components/data/Mini-VLAT/AreaChart.png'
|
||||
|
||||
|
||||
|
||||
class AreaChartMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawAreaChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawAreaChart()
|
||||
}
|
||||
|
||||
|
||||
drawAreaChart() {
|
||||
//https://www.ico.org/new_historical.asp
|
||||
//https://bl.ocks.org/interwebjill/8122dd08da9facf8c6ef6676be7da03f
|
||||
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
svg.append("text").attr("class", 'bubbleTitle').text("Average Coffee Bean Price from 2013 to 2014").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img10).attr('height', 1.1 * height)
|
||||
|
||||
}
|
||||
else {
|
||||
// var e = document.getElementById("graph_box");
|
||||
// const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`)
|
||||
|
||||
var data = [0.8865, 0.8924, 0.8818, 0.8831, 0.8874, 0.8607, 0.8442, 0.8074, 0.7670, 0.8532, 0.8352, 0.7757, 0.7824, 0.7865, 0.7696, 0.7328, 0.7112, 0.7402, 0.7393, 0.7078, 0.7064, 0.6863, 0.7328, 0.7322]
|
||||
|
||||
var xScale = d3.scaleTime()
|
||||
.domain([new Date(2018, 0, 1), new Date(2020, 0, 1)])
|
||||
.range([0, width]);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(xScale))
|
||||
|
||||
var yScale = d3.scaleLinear()
|
||||
.domain([0.5, 0.9])
|
||||
.range([height, 0]);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y-axis")
|
||||
.call(d3.axisLeft(yScale))
|
||||
|
||||
|
||||
var x = d3.scaleTime().domain([0, data.length - 1]).range([0, width]);
|
||||
var y = d3.scaleLinear().domain([0.5, 0.9]).range([height, 0]);
|
||||
|
||||
var area = d3.area()
|
||||
.x(function (d, i) {
|
||||
return x(i);
|
||||
})
|
||||
.y0(height)
|
||||
.y1(function (d) {
|
||||
return y(d);
|
||||
})
|
||||
|
||||
svg.append("path")
|
||||
.datum(data)
|
||||
.attr("fill", "#3182bd")
|
||||
.attr("stroke-width", 1.5)
|
||||
.attr("opacity", 0.6)
|
||||
.attr("d", area)
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return 0 - margin.left + 0.1 * (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else if (width < 400) {
|
||||
return 0 - margin.left + 0.005 * (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return 0 - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", 0 - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Coffee Price ($/lb)")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
function make_x_gridlines() {
|
||||
return d3.axisBottom(xScale).ticks(8);
|
||||
}
|
||||
|
||||
// gridlines in y axis function
|
||||
function make_y_gridlines() {
|
||||
return d3.axisLeft(yScale)
|
||||
.ticks(11)
|
||||
}
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(make_x_gridlines()
|
||||
.tickSize(-height)
|
||||
.tickFormat("").ticks(8)
|
||||
)
|
||||
|
||||
// add the Y gridlines
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_gridlines()
|
||||
.tickSize(-width)
|
||||
.tickFormat("")
|
||||
)
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", width / 3)
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Robusta Coffee Price")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AreaChartMini;
|
||||
162
ReactTool/frontend/src/components/barChart-mini.js
Normal file
@@ -0,0 +1,162 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/BarGraph.csv';
|
||||
import img9 from '../components/data/Mini-VLAT/BarChart.png'
|
||||
|
||||
|
||||
|
||||
class BarChartMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
//var e = document.getElementById("graph_box");
|
||||
//e.addEventListener('resize', this.divResize.bind(this))
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://www.speedtest.net/global-index (for October 21)
|
||||
//https://www.d3-graph-gallery.com/graph/barplot_ordered.html
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Average Internet Speeds in Asia").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img9).attr('height', 1.1 * height)
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`)
|
||||
|
||||
d3.csv(data).then(function (data) {
|
||||
data.forEach(function (d) {
|
||||
d.Speed = parseFloat(d.Speed);
|
||||
d.Country = d.Country;
|
||||
})
|
||||
const x = d3.scaleBand()
|
||||
.range([0, width])
|
||||
.domain(data.map(d => d.Country))
|
||||
.padding(0.3);
|
||||
|
||||
svg.append("g")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(x))
|
||||
.selectAll("text")
|
||||
.attr("y", 10)
|
||||
.attr("x", 9)
|
||||
.attr("class", "x-axis")
|
||||
.attr("dy", ".35em")
|
||||
.attr("transform", "rotate(40)")
|
||||
.style("text-anchor", "start")
|
||||
// .attr("transform", "translate(10,-10)rotate(-180)")
|
||||
//.style("text-anchor", "end");
|
||||
|
||||
// Add Y axis
|
||||
const y = d3.scaleLinear()
|
||||
.domain([5, 100])
|
||||
.range([height, 0]);
|
||||
|
||||
svg.append("g")
|
||||
.call(d3.axisLeft(y).tickSizeOuter(0))
|
||||
.selectAll("text")
|
||||
.attr("class", "y-axis");
|
||||
|
||||
function make_y_axis() {
|
||||
return d3.axisLeft(y).ticks(11).tickSizeInner(-width + margin.left + margin.right);
|
||||
}
|
||||
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_axis()
|
||||
.tickSize(-width, 0, 0)
|
||||
.tickFormat("")
|
||||
.tickSizeOuter(0)
|
||||
)
|
||||
|
||||
// Bars
|
||||
svg.selectAll("mybar")
|
||||
.data(data)
|
||||
.enter()
|
||||
.append("rect")
|
||||
.attr("x", d => x(d.Country))
|
||||
.attr("y", d => y(d.Speed))
|
||||
.attr("width", x.bandwidth())
|
||||
.attr("height", d => height - y(d.Speed))
|
||||
.attr("fill", "#3182bd")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (Math.min(length, height) < 500) {
|
||||
return 0.1 * margin.left + (- 3 * margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return 0 - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", 0 - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Internet Speed (Mbps)")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("x", width / 4)
|
||||
.attr("y", -3 * length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Global Internet Speed (Mbps)")
|
||||
.attr("class", "title")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BarChartMini;
|
||||
381
ReactTool/frontend/src/components/bubbleChart-mini.js
Normal file
@@ -0,0 +1,381 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/BubbleChart.csv';
|
||||
import img3 from '../components/data/Mini-VLAT/BubbleChart.png'
|
||||
|
||||
|
||||
|
||||
class BubbleChartMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://en.wikipedia.org/wiki/List_of_metro_systems
|
||||
//https://www.d3-graph-gallery.com/bubble
|
||||
var e = document.getElementById("graph_box");
|
||||
let length = Math.min(e.clientWidth, e.clientHeight);
|
||||
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Metro System of the World").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img3).attr('height', 1.1 * height)
|
||||
}
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`)
|
||||
|
||||
|
||||
d3.csv(data).then(function (data) {
|
||||
data.forEach(function (d) {
|
||||
d.City = d.City;
|
||||
d.Length = parseInt(d.Length);
|
||||
d.NumberofStations = parseInt(d.NumberofStations);
|
||||
d.Ridership = parseFloat(d.Ridership);
|
||||
})
|
||||
// Add X axis
|
||||
var x = d3.scaleLinear()
|
||||
.domain([150, 800])
|
||||
.range([0, width]);
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(d3.axisBottom(x))
|
||||
|
||||
// Add Y axis
|
||||
var y = d3.scaleLinear()
|
||||
.domain([150, 500])
|
||||
.range([height, 0]);
|
||||
svg.append("g")
|
||||
.attr("class", "y-axis")
|
||||
.call(d3.axisLeft(y))
|
||||
|
||||
// Add a scale for bubble size
|
||||
var z = d3.scaleLinear()
|
||||
.domain([0, 5])
|
||||
.range([0, length / 20]);
|
||||
|
||||
// Add dots
|
||||
var dots = svg.append('g')
|
||||
.selectAll("dot")
|
||||
.data(data)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", function (d) {
|
||||
return x(d.NumberofStations);
|
||||
})
|
||||
.attr("cy", function (d) {
|
||||
return y(d.Length);
|
||||
})
|
||||
.attr("r", function (d) {
|
||||
return z(d.Ridership);
|
||||
})
|
||||
.style("fill", "#3182bd")
|
||||
.style("opacity", "0.7")
|
||||
.attr("stroke", "black")
|
||||
|
||||
svg.selectAll("g")
|
||||
.selectAll("text")
|
||||
.data(data)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("x", function (d) {
|
||||
if (d.City === "Tokyo") {
|
||||
return x(d.NumberofStations) + z(d.Ridership) + z(d.Ridership) / 4;
|
||||
}
|
||||
else {
|
||||
return x(d.NumberofStations) + z(d.Ridership) + z(d.Ridership) / 2;
|
||||
}
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
if (d.City === "Tokyo") {
|
||||
return y(d.Length) + z(d.Ridership) - z(d.Ridership) / 2 - z(d.Ridership) / 2;
|
||||
}
|
||||
else {
|
||||
return y(d.Length) + z(d.Ridership) - z(d.Ridership) / 2;
|
||||
}
|
||||
})
|
||||
.attr("font-family", "sans-serif")
|
||||
.text(function (d) {
|
||||
return d.City;
|
||||
});
|
||||
|
||||
|
||||
function make_x_gridlines() {
|
||||
return d3.axisBottom(x).ticks(8);
|
||||
}
|
||||
|
||||
// gridlines in y axis function
|
||||
function make_y_gridlines() {
|
||||
return d3.axisLeft(y)
|
||||
.ticks(11)
|
||||
}
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(make_x_gridlines()
|
||||
.tickSize(-height)
|
||||
.tickFormat("").ticks(11)
|
||||
)
|
||||
|
||||
// add the Y gridlines
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_gridlines()
|
||||
.tickSize(-width)
|
||||
.tickFormat("")
|
||||
)
|
||||
|
||||
var size = d3.scaleSqrt()
|
||||
.domain([0, 5]) // What's in the data, let's say it is percentage
|
||||
.range([0, 40]) // Size in pixel
|
||||
|
||||
// Add legend: circles
|
||||
var valuesToShow = [3.5, 2.5, 1.5]
|
||||
var xCircle = width / 6
|
||||
var xLabel = height / 2
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "legend-title")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (0.1 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 400) {
|
||||
return 0.5 * height / margin.bottom
|
||||
}
|
||||
else {
|
||||
return height / margin.bottom
|
||||
}
|
||||
})
|
||||
.style("font-weight", "bold")
|
||||
.text("Ridership")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "legend-title")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return 0.94 * width + width / height
|
||||
}
|
||||
else {
|
||||
return width + width / height
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 400) {
|
||||
return height / (0.8 * margin.bottom)
|
||||
}
|
||||
else {
|
||||
return height / (0.3 * margin.bottom)
|
||||
}
|
||||
})
|
||||
.style("font-weight", "bold")
|
||||
.text("(bn per year)")
|
||||
|
||||
svg
|
||||
.selectAll("legend")
|
||||
.data(valuesToShow)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", xCircle * 6 + margin.left / 3.5)
|
||||
.attr("cy", function () {
|
||||
if (width < 500) {
|
||||
return xLabel / 4.0;
|
||||
}
|
||||
else {
|
||||
return xLabel / 5.5;
|
||||
}
|
||||
})
|
||||
.attr("r", z(3.5))
|
||||
.style("fill", "none")
|
||||
.attr("stroke", "black")
|
||||
|
||||
svg
|
||||
.selectAll("legend")
|
||||
.data(valuesToShow)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", xCircle * 6 + margin.left / 3.5)
|
||||
.attr("cy", function () {
|
||||
if (width < 500) {
|
||||
return xLabel / 4.0 + 2.8 * z(2.5)
|
||||
}
|
||||
else {
|
||||
return xLabel / 5.5 + 2.8 * z(2.5)
|
||||
}
|
||||
})
|
||||
.attr("r", z(2.5))
|
||||
.style("fill", "none")
|
||||
.attr("stroke", "black")
|
||||
|
||||
svg
|
||||
.selectAll("legend")
|
||||
.data(valuesToShow)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("cx", xCircle * 6 + margin.left / 3.5)
|
||||
.attr("cy", function () {
|
||||
if (width < 500) {
|
||||
return xLabel / 1.6 - (0.3) * z(2.5)
|
||||
}
|
||||
else {
|
||||
return xLabel / 1.9 - (0.3) * z(2.5);
|
||||
}
|
||||
})
|
||||
.attr("r", z(1.5))
|
||||
.style("fill", "none")
|
||||
.attr("stroke", "black")
|
||||
// Add legend: labels
|
||||
svg
|
||||
.selectAll("legend")
|
||||
.data(valuesToShow)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("class", "legend-value")
|
||||
.attr('x', xCircle * 6 + margin.left / 1.7)
|
||||
.attr('y', function () {
|
||||
if (width < 500) {
|
||||
return xLabel / 4.0
|
||||
}
|
||||
else {
|
||||
return xLabel / 5.5
|
||||
}
|
||||
})
|
||||
.text(3.5)
|
||||
.attr('alignment-baseline', 'middle')
|
||||
|
||||
svg
|
||||
.selectAll("legend")
|
||||
.data(valuesToShow)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("class", "legend-value")
|
||||
.attr('x', xCircle * 6 + margin.left / 1.7)
|
||||
.attr('y', function () {
|
||||
if (width < 500) {
|
||||
return xLabel / 4.0 + 2.8 * z(2.5);
|
||||
}
|
||||
else {
|
||||
return xLabel / 5.5 + 2.8 * z(2.5);
|
||||
}
|
||||
})
|
||||
.text(2.5)
|
||||
.attr('alignment-baseline', 'middle')
|
||||
|
||||
svg
|
||||
.selectAll("legend")
|
||||
.data(valuesToShow)
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("class", "legend-value")
|
||||
.attr('x', xCircle * 6 + margin.left / 1.7)
|
||||
.attr('y', function () {
|
||||
if (width < 500) {
|
||||
return xLabel / 1.6 - (0.3) * z(2.5);
|
||||
}
|
||||
else {
|
||||
return xLabel / 1.9 - (0.3) * z(2.5);
|
||||
}
|
||||
})
|
||||
.text(1.5)
|
||||
.attr('alignment-baseline', 'middle')
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width > 400 && width < 500) {
|
||||
return 0 - margin.left + (margin.top / 6.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else if (width < 400) {
|
||||
return 0 - margin.left + 0.05 * (margin.top / 9.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return 0 - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", 0 - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Total System Length (Km)")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("transform", function () {
|
||||
if (width < 500) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.4 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.1 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
})
|
||||
.style("text-anchor", "middle")
|
||||
.style("font-weight", "bold")
|
||||
.text("Number of Stations")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", width / 3)
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Metro Systems of the World")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default BubbleChartMini;
|
||||
228
ReactTool/frontend/src/components/choropleth-mini.js
Normal file
@@ -0,0 +1,228 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data_usa from './data/USA.json';
|
||||
import data from './data/Choropleth.csv';
|
||||
import img8 from '../components/data/Mini-VLAT/Choropleth_New.png'
|
||||
|
||||
|
||||
|
||||
class ChoroplethMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log(String(data_usa))
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://www.statista.com/statistics/223675/state-unemployment-rate-in-the-us/
|
||||
//https://bl.ocks.org/wboykinm/dbbe50d1023f90d4e241712395c27fb3
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
|
||||
const margin = { top: length / 5, right: length / 5, bottom: length / 5, left: length / 5 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
// append the svg object to the body of the page
|
||||
//d3.select("#graph_box").selectAll("svg").remove();
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
|
||||
svg.append("text").attr("class", 'bubbleTitle').text("Unemployment Rates for States in 2020").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 0.9 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.4 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img8).attr('height', 1.1 * height)
|
||||
|
||||
// else {
|
||||
// const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
// width = length - margin.left - margin.right,
|
||||
// height = length - margin.top - margin.bottom;
|
||||
|
||||
// // append the svg object to the body of the page
|
||||
// //d3.select("#graph_box").selectAll("svg").remove();
|
||||
// d3.select("#graph_box").select("svg").remove();
|
||||
// const svg = d3.select("#graph_box")
|
||||
// .append("svg")
|
||||
// .attr("width", width + margin.left + margin.right)
|
||||
// .attr("height", height + margin.top + margin.bottom)
|
||||
// .append("g")
|
||||
// .attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
// // svg.append("text").attr("class", 'bubbleTitle').text("Unemployment Rates for States in 2015").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
// // var image = svg.append('image').attr('width', 1.4 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img8).attr('height', 1.1 * height)
|
||||
|
||||
// var projection = d3.geoAlbersUsa()
|
||||
// .translate([width / 2, height / 2])
|
||||
// .scale(Math.min(e.clientHeight, e.clientWidth));
|
||||
|
||||
// var path = d3.geoPath()
|
||||
// .projection(projection)
|
||||
|
||||
// var lowColor = '#f7fbff'
|
||||
// var highColor = '#084594'
|
||||
|
||||
// d3.csv(data).then(function (data) {
|
||||
// var names = {};
|
||||
// data.forEach(function (d) {
|
||||
// d.state = d.state;
|
||||
// d.value = parseFloat(d.value);
|
||||
// names[d.id] = d.code;
|
||||
// })
|
||||
// var dataArr = [];
|
||||
// for (var d = 0; d < data.length; d++) {
|
||||
// dataArr.push(parseFloat(data[d].value))
|
||||
// }
|
||||
// var minVal = d3.min(dataArr);
|
||||
// var maxVal = d3.max(dataArr);
|
||||
// var ramp = d3.scaleLinear().domain([minVal, maxVal]).range([lowColor, highColor])
|
||||
|
||||
// for (var i = 0; i < data.length; i++) {
|
||||
// var dataState = data[i].state;
|
||||
// var dataVal = data[i].value;
|
||||
// var usa = topojson.feature(data_usa, data_usa.objects.states).features;
|
||||
// for (var j = 0; j < usa.length; j++) {
|
||||
// var jsonState = usa[j].properties.name;
|
||||
// if (dataState == jsonState) {
|
||||
// usa[j].properties.value = dataVal;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// // Render the U.S. by using the path generator
|
||||
// svg.selectAll("path")
|
||||
// .data(usa)
|
||||
// .enter().append("path")
|
||||
// .attr("d", path)
|
||||
// .style("stroke", "#ffff")
|
||||
// .style("stroke-width", "1")
|
||||
// .style("fill", function (d) {
|
||||
// return ramp(d.properties.value)
|
||||
// });
|
||||
|
||||
// svg.selectAll("text").data(usa).enter().append("text")
|
||||
// .text(function (d) {
|
||||
// return names[d.id];
|
||||
// })
|
||||
// .attr("x", function (d) {
|
||||
// return path.centroid(d)[0];
|
||||
// })
|
||||
// .attr("y", function (d) {
|
||||
// return path.centroid(d)[1];
|
||||
// })
|
||||
// .attr("class", "state-abbr")
|
||||
// .attr("text-anchor", "middle")
|
||||
// .attr("fill", "black")
|
||||
// .style("font-weight", "bold")
|
||||
|
||||
// //var w = e.clientWidth/4, h = e.clientHeight/6;
|
||||
// //d3.select("body").select("svg").remove();
|
||||
// //d3.selectAll("svg").select(".legend").remove();
|
||||
|
||||
// var legend = svg.append("defs")
|
||||
// .append("svg:linearGradient")
|
||||
// .attr("id", "gradient")
|
||||
// .attr("x1", "0%")
|
||||
// .attr("y1", "100%")
|
||||
// .attr("x2", "100%")
|
||||
// .attr("y2", "100%")
|
||||
// .attr("spreadMethod", "pad");
|
||||
|
||||
// legend.append("stop")
|
||||
// .attr("offset", "0%")
|
||||
// .attr("stop-color", highColor)
|
||||
// .attr("stop-opacity", 1);
|
||||
|
||||
// legend.append("stop")
|
||||
// .attr("offset", "100%")
|
||||
// .attr("stop-color", lowColor)
|
||||
// .attr("stop-opacity", 1);
|
||||
|
||||
// if (width < 350) {
|
||||
// svg.append("rect")
|
||||
// .attr("width", length / 4)
|
||||
// .attr("height", length / 5.5 - margin.top)
|
||||
// .style("fill", "url(#gradient)")
|
||||
// .attr("transform", "translate(0," + (length / 5.4 - margin.left / 0.8) + ")");
|
||||
|
||||
// svg.append("text").attr("x", 0).attr("y", length / 8.5 - 0.4 * margin.top).text("12%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 20).attr("y", length / 8.5 - 0.4 * margin.top).text("10%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 10).attr("y", length / 8.5 - 0.4 * margin.top).text("8%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 7).attr("y", length / 8.5 - 0.4 * margin.top).text("6%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 5).attr("y", length / 8.5 - 0.4 * margin.top).text("4%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// }
|
||||
// else {
|
||||
// svg.append("rect")
|
||||
// .attr("width", length / 4)
|
||||
// .attr("height", length / 5.5 - margin.top)
|
||||
// .style("fill", "url(#gradient)")
|
||||
// .attr("transform", "translate(0," + (length / 5.4 - margin.left / 1) + ")");
|
||||
|
||||
// svg.append("text").attr("x", 0).attr("y", length / 6.5 - 0.4 * margin.top).text("12%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 20).attr("y", length / 6.5 - 0.4 * margin.top).text("10%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 10).attr("y", length / 6.5 - 0.4 * margin.top).text("8%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 7).attr("y", length / 6.5 - 0.4 * margin.top).text("6%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// svg.append("text").attr("x", length / 5).attr("y", length / 6.5 - 0.4 * margin.top).text("4%").style("font-weight", "bold").attr("class", "legend-value")
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// /*
|
||||
// var y = d3.scaleLinear()
|
||||
// .range([length/4 - length/3.3, length/4.4 - length/(margin.left/4.0)])
|
||||
// //.domain([maxVal, minVal]);
|
||||
// //ar formatPercent = d3.format("%");
|
||||
// var yAxis = d3.axisBottom(y).tickValues(["12%", "11%", "10%", "9%"]);
|
||||
// svg.append("g")
|
||||
// //.attr("class", "axis")
|
||||
// .attr("transform", "translate(" + (length/5.45-margin.left/1.1) + "," + margin.right/0.75 + ")")
|
||||
// .call(yAxis)
|
||||
// .style("font-weight", "bold")
|
||||
// .style("font-size", 1.3*(length/margin.top)); */
|
||||
|
||||
// svg
|
||||
// .append("text")
|
||||
// .attr("x", width / 5.5)
|
||||
// .attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
// .text("Unemployment Rate for States in 2020 ")
|
||||
// .attr("class", "title")
|
||||
// .attr("fill", "black")
|
||||
// .style("font-weight", "bold")
|
||||
|
||||
// });
|
||||
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ChoroplethMini;
|
||||
@@ -0,0 +1,5 @@
|
||||
Countries,Gold,Silver,Bronze
|
||||
U.S.A.,34.5,36.3,29.2
|
||||
Great Britain,33.8,32.3,33.9
|
||||
Japan,46.6,24.1,29.3
|
||||
Australia,37,15.2,47.8
|
||||
|
25
ReactTool/frontend/src/components/data/AreaChart-2.csv
Normal file
@@ -0,0 +1,25 @@
|
||||
date,value
|
||||
Jan-2018,88.65
|
||||
Feb-2018,89.24
|
||||
Mar-2018,88.18
|
||||
Apr-2018,88.31
|
||||
May-2018,88.74
|
||||
Jun-2018,86.07
|
||||
Jul-2018,84.42
|
||||
Aug-2018,80.74
|
||||
Sep-2018,76.70
|
||||
Oct-2018,85.32
|
||||
Nov-2018,83.52
|
||||
Dec-2018,77.57
|
||||
Jan-2019,78.24
|
||||
Feb-2019,78.65
|
||||
Mar-2019,76.96
|
||||
Apr-2019,73.28
|
||||
May-2019,71.12
|
||||
Jun-2019,74.02
|
||||
Jul-2019,73.93
|
||||
Aug-2019,70.78
|
||||
Sep-2019,70.64
|
||||
Oct-2019,68.63
|
||||
Nov-2019,73.28
|
||||
Dec-2019,73.22
|
||||
|
979
ReactTool/frontend/src/components/data/AreaChart.csv
Normal file
@@ -0,0 +1,979 @@
|
||||
date,value
|
||||
2013-04-28,135.98
|
||||
2013-04-29,147.49
|
||||
2013-04-30,146.93
|
||||
2013-05-01,139.89
|
||||
2013-05-02,125.6
|
||||
2013-05-03,108.13
|
||||
2013-05-04,115
|
||||
2013-05-05,118.8
|
||||
2013-05-06,124.66
|
||||
2013-05-07,113.44
|
||||
2013-05-08,115.78
|
||||
2013-05-09,113.46
|
||||
2013-05-10,122
|
||||
2013-05-11,118.68
|
||||
2013-05-12,117.45
|
||||
2013-05-13,118.7
|
||||
2013-05-14,119.8
|
||||
2013-05-15,115.81
|
||||
2013-05-16,118.76
|
||||
2013-05-17,125.3
|
||||
2013-05-18,125.25
|
||||
2013-05-19,124.5
|
||||
2013-05-20,123.62
|
||||
2013-05-21,123
|
||||
2013-05-22,124
|
||||
2013-05-23,126.93
|
||||
2013-05-24,133.85
|
||||
2013-05-25,133.22
|
||||
2013-05-26,136
|
||||
2013-05-27,135.47
|
||||
2013-05-28,130.58
|
||||
2013-05-29,132.59
|
||||
2013-05-30,132.25
|
||||
2013-05-31,129.9
|
||||
2013-06-01,129.78
|
||||
2013-06-02,129.4
|
||||
2013-06-03,122.5
|
||||
2013-06-04,123.84
|
||||
2013-06-05,123.47
|
||||
2013-06-06,123.1
|
||||
2013-06-07,119
|
||||
2013-06-08,111.42
|
||||
2013-06-09,108.99
|
||||
2013-06-10,110.1
|
||||
2013-06-11,109.6
|
||||
2013-06-12,111.79
|
||||
2013-06-13,110.3
|
||||
2013-06-14,104.7
|
||||
2013-06-15,103.7
|
||||
2013-06-16,101.6
|
||||
2013-06-17,102.21
|
||||
2013-06-18,111.11
|
||||
2013-06-19,110.22
|
||||
2013-06-20,114.3
|
||||
2013-06-21,114.99
|
||||
2013-06-22,109.96
|
||||
2013-06-23,108.8
|
||||
2013-06-24,108.33
|
||||
2013-06-25,106.47
|
||||
2013-06-26,105.49
|
||||
2013-06-27,104
|
||||
2013-06-28,101.74
|
||||
2013-06-29,99.99
|
||||
2013-06-30,98.12
|
||||
2013-07-01,97.66
|
||||
2013-07-02,92.3
|
||||
2013-07-03,90.98
|
||||
2013-07-04,83.11
|
||||
2013-07-05,80
|
||||
2013-07-06,75
|
||||
2013-07-07,74.56
|
||||
2013-07-08,80
|
||||
2013-07-09,78.3
|
||||
2013-07-10,87
|
||||
2013-07-11,90.28
|
||||
2013-07-12,104
|
||||
2013-07-13,98.25
|
||||
2013-07-14,98.7
|
||||
2013-07-15,101.9
|
||||
2013-07-16,99.86
|
||||
2013-07-17,99.97
|
||||
2013-07-18,98.8
|
||||
2013-07-19,95.2
|
||||
2013-07-20,93.1
|
||||
2013-07-21,91.95
|
||||
2013-07-22,92
|
||||
2013-07-23,96.82
|
||||
2013-07-24,95.99
|
||||
2013-07-25,97.33
|
||||
2013-07-26,97.47
|
||||
2013-07-27,97
|
||||
2013-07-28,100.58
|
||||
2013-07-29,102.5
|
||||
2013-07-30,107.99
|
||||
2013-07-31,111.34
|
||||
2013-08-01,108
|
||||
2013-08-02,108
|
||||
2013-08-03,105.78
|
||||
2013-08-04,105.95
|
||||
2013-08-05,107.77
|
||||
2013-08-06,107.38
|
||||
2013-08-07,106.75
|
||||
2013-08-08,106.75
|
||||
2013-08-09,105.75
|
||||
2013-08-10,103.9
|
||||
2013-08-11,105.19
|
||||
2013-08-12,108
|
||||
2013-08-13,109.35
|
||||
2013-08-14,115
|
||||
2013-08-15,113.25
|
||||
2013-08-16,112.3
|
||||
2013-08-17,113.75
|
||||
2013-08-18,114.69
|
||||
2013-08-19,123.06
|
||||
2013-08-20,123.01
|
||||
2013-08-21,124.91
|
||||
2013-08-22,123.5
|
||||
2013-08-23,122
|
||||
2013-08-24,121.39
|
||||
2013-08-25,122.99
|
||||
2013-08-26,122.75
|
||||
2013-08-27,127.24
|
||||
2013-08-28,127.32
|
||||
2013-08-29,123.7
|
||||
2013-08-30,135.75
|
||||
2013-08-31,140.89
|
||||
2013-09-01,145.81
|
||||
2013-09-02,146.5
|
||||
2013-09-03,138.34
|
||||
2013-09-04,144.5
|
||||
2013-09-05,131.44
|
||||
2013-09-06,127.34
|
||||
2013-09-07,125.94
|
||||
2013-09-08,124.72
|
||||
2013-09-09,129.06
|
||||
2013-09-10,129.74
|
||||
2013-09-11,137.83
|
||||
2013-09-12,136.08
|
||||
2013-09-13,137.58
|
||||
2013-09-14,135.85
|
||||
2013-09-15,131.44
|
||||
2013-09-16,132.72
|
||||
2013-09-17,132.76
|
||||
2013-09-18,133.2
|
||||
2013-09-19,131.77
|
||||
2013-09-20,135.62
|
||||
2013-09-21,128.61
|
||||
2013-09-22,133.94
|
||||
2013-09-23,132.72
|
||||
2013-09-24,127.46
|
||||
2013-09-25,129.69
|
||||
2013-09-26,134.93
|
||||
2013-09-27,134.74
|
||||
2013-09-28,135.63
|
||||
2013-09-29,140.61
|
||||
2013-09-30,138.35
|
||||
2013-10-01,134.63
|
||||
2013-10-02,133.59
|
||||
2013-10-03,123.63
|
||||
2013-10-04,130.09
|
||||
2013-10-05,130.44
|
||||
2013-10-06,129.66
|
||||
2013-10-07,130.27
|
||||
2013-10-08,127.47
|
||||
2013-10-09,131.75
|
||||
2013-10-10,131.5
|
||||
2013-10-11,131.81
|
||||
2013-10-12,135.66
|
||||
2013-10-13,138.66
|
||||
2013-10-14,144.12
|
||||
2013-10-15,145.39
|
||||
2013-10-16,152.23
|
||||
2013-10-17,147.42
|
||||
2013-10-18,155.96
|
||||
2013-10-19,177.48
|
||||
2013-10-20,174.91
|
||||
2013-10-21,184.82
|
||||
2013-10-22,196.27
|
||||
2013-10-23,213.62
|
||||
2013-10-24,217.42
|
||||
2013-10-25,198.87
|
||||
2013-10-26,188.41
|
||||
2013-10-27,196.44
|
||||
2013-10-28,198.62
|
||||
2013-10-29,204.79
|
||||
2013-10-30,209.16
|
||||
2013-10-31,205.18
|
||||
2013-11-01,206.65
|
||||
2013-11-02,207.76
|
||||
2013-11-03,215.05
|
||||
2013-11-04,231.01
|
||||
2013-11-05,250.66
|
||||
2013-11-06,263
|
||||
2013-11-07,304.17
|
||||
2013-11-08,338.66
|
||||
2013-11-09,370.82
|
||||
2013-11-10,350.7
|
||||
2013-11-11,351.27
|
||||
2013-11-12,362.81
|
||||
2013-11-13,414.05
|
||||
2013-11-14,425.9
|
||||
2013-11-15,437.89
|
||||
2013-11-16,450.26
|
||||
2013-11-17,500.58
|
||||
2013-11-18,703.78
|
||||
2013-11-19,806.11
|
||||
2013-11-20,599.65
|
||||
2013-11-21,733.4
|
||||
2013-11-22,780.85
|
||||
2013-11-23,844.97
|
||||
2013-11-24,807.36
|
||||
2013-11-25,810.68
|
||||
2013-11-26,928.54
|
||||
2013-11-27,1001.96
|
||||
2013-11-28,1077.56
|
||||
2013-11-29,1146.97
|
||||
2013-11-30,1156.14
|
||||
2013-12-01,1133.08
|
||||
2013-12-02,1055.42
|
||||
2013-12-03,1096
|
||||
2013-12-04,1156.12
|
||||
2013-12-05,1154.36
|
||||
2013-12-06,1042.38
|
||||
2013-12-07,854.64
|
||||
2013-12-08,802.51
|
||||
2013-12-09,921.93
|
||||
2013-12-10,997.23
|
||||
2013-12-11,1001.58
|
||||
2013-12-12,901.94
|
||||
2013-12-13,941.79
|
||||
2013-12-14,904.65
|
||||
2013-12-15,886.16
|
||||
2013-12-16,882.25
|
||||
2013-12-17,754.83
|
||||
2013-12-18,679.32
|
||||
2013-12-19,707.23
|
||||
2013-12-20,729.16
|
||||
2013-12-21,654.27
|
||||
2013-12-22,666.74
|
||||
2013-12-23,680.91
|
||||
2013-12-24,684.39
|
||||
2013-12-25,682.7
|
||||
2013-12-26,777.75
|
||||
2013-12-27,777.51
|
||||
2013-12-28,747.06
|
||||
2013-12-29,748.61
|
||||
2013-12-30,766.6
|
||||
2013-12-31,760.58
|
||||
2014-01-01,775.35
|
||||
2014-01-02,820.31
|
||||
2014-01-03,834.15
|
||||
2014-01-04,859.51
|
||||
2014-01-05,952.4
|
||||
2014-01-06,1017.12
|
||||
2014-01-07,965.74
|
||||
2014-01-08,870.68
|
||||
2014-01-09,864.36
|
||||
2014-01-10,871.19
|
||||
2014-01-11,921.48
|
||||
2014-01-12,928.52
|
||||
2014-01-13,861.29
|
||||
2014-01-14,855.69
|
||||
2014-01-15,872.81
|
||||
2014-01-16,866.16
|
||||
2014-01-17,842.91
|
||||
2014-01-18,841.49
|
||||
2014-01-19,870.96
|
||||
2014-01-20,886.39
|
||||
2014-01-21,881.2
|
||||
2014-01-22,870.15
|
||||
2014-01-23,851.57
|
||||
2014-01-24,822.43
|
||||
2014-01-25,861.45
|
||||
2014-01-26,897.02
|
||||
2014-01-27,893
|
||||
2014-01-28,832.5
|
||||
2014-01-29,836.87
|
||||
2014-01-30,830.5
|
||||
2014-01-31,831.87
|
||||
2014-02-01,853.52
|
||||
2014-02-02,844.72
|
||||
2014-02-03,826.48
|
||||
2014-02-04,840.17
|
||||
2014-02-05,837.32
|
||||
2014-02-06,819.81
|
||||
2014-02-07,783.2
|
||||
2014-02-08,721.82
|
||||
2014-02-09,712.27
|
||||
2014-02-10,703.71
|
||||
2014-02-11,712.46
|
||||
2014-02-12,672.9
|
||||
2014-02-13,657.99
|
||||
2014-02-14,691.72
|
||||
2014-02-15,661.84
|
||||
2014-02-16,665.1
|
||||
2014-02-17,656.95
|
||||
2014-02-18,645.76
|
||||
2014-02-19,631.77
|
||||
2014-02-20,627.73
|
||||
2014-02-21,582.96
|
||||
2014-02-22,614.48
|
||||
2014-02-23,639.91
|
||||
2014-02-24,607.61
|
||||
2014-02-25,541.38
|
||||
2014-02-26,603.8
|
||||
2014-02-27,594.05
|
||||
2014-02-28,584.14
|
||||
2014-03-01,573.38
|
||||
2014-03-02,570.48
|
||||
2014-03-03,702.91
|
||||
2014-03-04,696.22
|
||||
2014-03-05,674.28
|
||||
2014-03-06,669.77
|
||||
2014-03-07,665.34
|
||||
2014-03-08,635.14
|
||||
2014-03-09,643.95
|
||||
2014-03-10,644.76
|
||||
2014-03-11,638.42
|
||||
2014-03-12,648.03
|
||||
2014-03-13,644.2
|
||||
2014-03-14,639.53
|
||||
2014-03-15,639.14
|
||||
2014-03-16,637.52
|
||||
2014-03-17,632.68
|
||||
2014-03-18,622.39
|
||||
2014-03-19,622
|
||||
2014-03-20,609.75
|
||||
2014-03-21,604.59
|
||||
2014-03-22,572.55
|
||||
2014-03-23,570.24
|
||||
2014-03-24,586.56
|
||||
2014-03-25,585.44
|
||||
2014-03-26,590.03
|
||||
2014-03-27,580.56
|
||||
2014-03-28,526.02
|
||||
2014-03-29,504.86
|
||||
2014-03-30,492.37
|
||||
2014-03-31,483.02
|
||||
2014-04-01,495.34
|
||||
2014-04-02,495.05
|
||||
2014-04-03,449.56
|
||||
2014-04-04,454.65
|
||||
2014-04-05,463.57
|
||||
2014-04-06,466.32
|
||||
2014-04-07,462.56
|
||||
2014-04-08,457.42
|
||||
2014-04-09,455.73
|
||||
2014-04-10,443.37
|
||||
2014-04-11,429.77
|
||||
2014-04-12,439.61
|
||||
2014-04-13,427.4
|
||||
2014-04-14,469.75
|
||||
2014-04-15,519
|
||||
2014-04-16,542.38
|
||||
2014-04-17,533.52
|
||||
2014-04-18,498.6
|
||||
2014-04-19,503.56
|
||||
2014-04-20,510.87
|
||||
2014-04-21,510.57
|
||||
2014-04-22,503.22
|
||||
2014-04-23,493.25
|
||||
2014-04-24,500.46
|
||||
2014-04-25,500.3
|
||||
2014-04-26,464.54
|
||||
2014-04-27,459.33
|
||||
2014-04-28,447.53
|
||||
2014-04-29,451.64
|
||||
2014-04-30,451.1
|
||||
2014-05-01,460.61
|
||||
2014-05-02,457.93
|
||||
2014-05-03,449.4
|
||||
2014-05-04,439.77
|
||||
2014-05-05,440.97
|
||||
2014-05-06,448.04
|
||||
2014-05-07,446.13
|
||||
2014-05-08,448.4
|
||||
2014-05-09,452.69
|
||||
2014-05-10,455.77
|
||||
2014-05-11,455.34
|
||||
2014-05-12,442.26
|
||||
2014-05-13,441.98
|
||||
2014-05-14,446.66
|
||||
2014-05-15,449.8
|
||||
2014-05-16,450.66
|
||||
2014-05-17,451.98
|
||||
2014-05-18,449.77
|
||||
2014-05-19,447.56
|
||||
2014-05-20,491.44
|
||||
2014-05-21,494.37
|
||||
2014-05-22,525.36
|
||||
2014-05-23,541.96
|
||||
2014-05-24,525.17
|
||||
2014-05-25,576.48
|
||||
2014-05-26,588.39
|
||||
2014-05-27,589.52
|
||||
2014-05-28,578.62
|
||||
2014-05-29,577.1
|
||||
2014-05-30,618.46
|
||||
2014-05-31,624.72
|
||||
2014-06-01,671.51
|
||||
2014-06-02,665.5
|
||||
2014-06-03,674.11
|
||||
2014-06-04,668.56
|
||||
2014-06-05,663.53
|
||||
2014-06-06,661.37
|
||||
2014-06-07,656.94
|
||||
2014-06-08,658.88
|
||||
2014-06-09,657.7
|
||||
2014-06-10,659.62
|
||||
2014-06-11,657.04
|
||||
2014-06-12,638.11
|
||||
2014-06-13,615.14
|
||||
2014-06-14,601.27
|
||||
2014-06-15,592.94
|
||||
2014-06-16,608.72
|
||||
2014-06-17,610.89
|
||||
2014-06-18,615.88
|
||||
2014-06-19,612.24
|
||||
2014-06-20,599.75
|
||||
2014-06-21,599.46
|
||||
2014-06-22,606
|
||||
2014-06-23,603.21
|
||||
2014-06-24,596.97
|
||||
2014-06-25,583.6
|
||||
2014-06-26,581.63
|
||||
2014-06-27,600.12
|
||||
2014-06-28,604.47
|
||||
2014-06-29,604.08
|
||||
2014-06-30,645.15
|
||||
2014-07-01,657.86
|
||||
2014-07-02,656.68
|
||||
2014-07-03,650.77
|
||||
2014-07-04,648.43
|
||||
2014-07-05,633.22
|
||||
2014-07-06,638.65
|
||||
2014-07-07,637.16
|
||||
2014-07-08,626.7
|
||||
2014-07-09,627
|
||||
2014-07-10,626.12
|
||||
2014-07-11,632.09
|
||||
2014-07-12,636.66
|
||||
2014-07-13,634.73
|
||||
2014-07-14,627.34
|
||||
2014-07-15,625.14
|
||||
2014-07-16,623.09
|
||||
2014-07-17,626.29
|
||||
2014-07-18,629.21
|
||||
2014-07-19,629.17
|
||||
2014-07-20,628.56
|
||||
2014-07-21,624.09
|
||||
2014-07-22,624.3
|
||||
2014-07-23,624.43
|
||||
2014-07-24,620.43
|
||||
2014-07-25,607.07
|
||||
2014-07-26,602.09
|
||||
2014-07-27,598.94
|
||||
2014-07-28,594.57
|
||||
2014-07-29,588.38
|
||||
2014-07-30,585.12
|
||||
2014-07-31,586.24
|
||||
2014-08-01,597.92
|
||||
2014-08-02,594.91
|
||||
2014-08-03,589.15
|
||||
2014-08-04,591.95
|
||||
2014-08-05,589.87
|
||||
2014-08-06,587.49
|
||||
2014-08-07,591.1
|
||||
2014-08-08,598.12
|
||||
2014-08-09,592.47
|
||||
2014-08-10,594.46
|
||||
2014-08-11,591.51
|
||||
2014-08-12,576.95
|
||||
2014-08-13,573.03
|
||||
2014-08-14,546.24
|
||||
2014-08-15,518.18
|
||||
2014-08-16,521.48
|
||||
2014-08-17,520.19
|
||||
2014-08-18,499.37
|
||||
2014-08-19,485.71
|
||||
2014-08-20,518.28
|
||||
2014-08-21,531.9
|
||||
2014-08-22,521.48
|
||||
2014-08-23,514.3
|
||||
2014-08-24,512.89
|
||||
2014-08-25,508.22
|
||||
2014-08-26,512.69
|
||||
2014-08-27,520.71
|
||||
2014-08-28,516.16
|
||||
2014-08-29,511.69
|
||||
2014-08-30,509.31
|
||||
2014-08-31,504.88
|
||||
2014-09-01,485.31
|
||||
2014-09-02,482.99
|
||||
2014-09-03,481.71
|
||||
2014-09-04,493.93
|
||||
2014-09-05,490.64
|
||||
2014-09-06,488.6
|
||||
2014-09-07,488.07
|
||||
2014-09-08,489.83
|
||||
2014-09-09,477.38
|
||||
2014-09-10,487.47
|
||||
2014-09-11,482.35
|
||||
2014-09-12,479.63
|
||||
2014-09-13,482.12
|
||||
2014-09-14,479.85
|
||||
2014-09-15,478.62
|
||||
2014-09-16,475.64
|
||||
2014-09-17,468.17
|
||||
2014-09-18,456.86
|
||||
2014-09-19,427.83
|
||||
2014-09-20,423.3
|
||||
2014-09-21,412.43
|
||||
2014-09-22,406.92
|
||||
2014-09-23,441.56
|
||||
2014-09-24,436.11
|
||||
2014-09-25,423.52
|
||||
2014-09-26,414.94
|
||||
2014-09-27,406.62
|
||||
2014-09-28,401.02
|
||||
2014-09-29,385.21
|
||||
2014-09-30,390.98
|
||||
2014-10-01,391.38
|
||||
2014-10-02,385.5
|
||||
2014-10-03,377.69
|
||||
2014-10-04,364.49
|
||||
2014-10-05,341.8
|
||||
2014-10-06,345.13
|
||||
2014-10-07,339.25
|
||||
2014-10-08,354.36
|
||||
2014-10-09,382.73
|
||||
2014-10-10,375.07
|
||||
2014-10-11,367.19
|
||||
2014-10-12,379.43
|
||||
2014-10-13,397.23
|
||||
2014-10-14,411.7
|
||||
2014-10-15,402.23
|
||||
2014-10-16,398.81
|
||||
2014-10-17,385.48
|
||||
2014-10-18,395.16
|
||||
2014-10-19,393.94
|
||||
2014-10-20,390.08
|
||||
2014-10-21,392.65
|
||||
2014-10-22,388.58
|
||||
2014-10-23,385.05
|
||||
2014-10-24,364.35
|
||||
2014-10-25,359.86
|
||||
2014-10-26,359.22
|
||||
2014-10-27,358.63
|
||||
2014-10-28,359.98
|
||||
2014-10-29,357.83
|
||||
2014-10-30,350.91
|
||||
2014-10-31,348.05
|
||||
2014-11-01,340.53
|
||||
2014-11-02,329.05
|
||||
2014-11-03,334
|
||||
2014-11-04,331.77
|
||||
2014-11-05,343.37
|
||||
2014-11-06,352.97
|
||||
2014-11-07,352.73
|
||||
2014-11-08,347.03
|
||||
2014-11-09,363.63
|
||||
2014-11-10,374.82
|
||||
2014-11-11,371.31
|
||||
2014-11-12,429.72
|
||||
2014-11-13,457.09
|
||||
2014-11-14,419.25
|
||||
2014-11-15,405.53
|
||||
2014-11-16,390.8
|
||||
2014-11-17,410.2
|
||||
2014-11-18,392.4
|
||||
2014-11-19,386.48
|
||||
2014-11-20,382.02
|
||||
2014-11-21,357.88
|
||||
2014-11-22,364.84
|
||||
2014-11-23,370.85
|
||||
2014-11-24,387.21
|
||||
2014-11-25,394.7
|
||||
2014-11-26,377.7
|
||||
2014-11-27,373.99
|
||||
2014-11-28,382.84
|
||||
2014-11-29,387.6
|
||||
2014-11-30,382.53
|
||||
2014-12-01,383.66
|
||||
2014-12-02,384.04
|
||||
2014-12-03,383.03
|
||||
2014-12-04,378.65
|
||||
2014-12-05,379.19
|
||||
2014-12-06,378.45
|
||||
2014-12-07,376.29
|
||||
2014-12-08,376.03
|
||||
2014-12-09,363.07
|
||||
2014-12-10,352.38
|
||||
2014-12-11,361.36
|
||||
2014-12-12,352.98
|
||||
2014-12-13,352.38
|
||||
2014-12-14,353.32
|
||||
2014-12-15,351.81
|
||||
2014-12-16,345.86
|
||||
2014-12-17,333.95
|
||||
2014-12-18,323.71
|
||||
2014-12-19,318.53
|
||||
2014-12-20,330.32
|
||||
2014-12-21,329.63
|
||||
2014-12-22,334.12
|
||||
2014-12-23,336.29
|
||||
2014-12-24,334.74
|
||||
2014-12-25,322.67
|
||||
2014-12-26,331.42
|
||||
2014-12-27,328.91
|
||||
2014-12-28,320.03
|
||||
2014-12-29,320.27
|
||||
2014-12-30,314.81
|
||||
2014-12-31,320.19
|
||||
2015-01-01,320.44
|
||||
2015-01-02,315.84
|
||||
2015-01-03,315.15
|
||||
2015-01-04,287.23
|
||||
2015-01-05,278.34
|
||||
2015-01-06,287.55
|
||||
2015-01-07,298.75
|
||||
2015-01-08,294.13
|
||||
2015-01-09,291.11
|
||||
2015-01-10,288.13
|
||||
2015-01-11,279.64
|
||||
2015-01-12,272.2
|
||||
2015-01-13,268.28
|
||||
2015-01-14,223.89
|
||||
2015-01-15,229.07
|
||||
2015-01-16,221.59
|
||||
2015-01-17,211.73
|
||||
2015-01-18,218.69
|
||||
2015-01-19,216.73
|
||||
2015-01-20,215.24
|
||||
2015-01-21,227.79
|
||||
2015-01-22,237.02
|
||||
2015-01-23,234.84
|
||||
2015-01-24,248.21
|
||||
2015-01-25,255.07
|
||||
2015-01-26,309.38
|
||||
2015-01-27,275.48
|
||||
2015-01-28,266.54
|
||||
2015-01-29,238.71
|
||||
2015-01-30,242.85
|
||||
2015-01-31,233.5
|
||||
2015-02-01,231.57
|
||||
2015-02-02,242.18
|
||||
2015-02-03,245.96
|
||||
2015-02-04,230.06
|
||||
2015-02-05,239.41
|
||||
2015-02-06,230.51
|
||||
2015-02-07,230.3
|
||||
2015-02-08,229.44
|
||||
2015-02-09,223.98
|
||||
2015-02-10,221.81
|
||||
2015-02-11,223.41
|
||||
2015-02-12,222.2
|
||||
2015-02-13,240.26
|
||||
2015-02-14,259.81
|
||||
2015-02-15,265.61
|
||||
2015-02-16,239.52
|
||||
2015-02-17,245.78
|
||||
2015-02-18,244.25
|
||||
2015-02-19,242.67
|
||||
2015-02-20,247.1
|
||||
2015-02-21,255.32
|
||||
2015-02-22,246.39
|
||||
2015-02-23,240.11
|
||||
2015-02-24,239.9
|
||||
2015-02-25,239.34
|
||||
2015-02-26,237.71
|
||||
2015-02-27,256.65
|
||||
2015-02-28,254.69
|
||||
2015-03-01,261.66
|
||||
2015-03-02,276.3
|
||||
2015-03-03,285.8
|
||||
2015-03-04,284.23
|
||||
2015-03-05,281.67
|
||||
2015-03-06,277.61
|
||||
2015-03-07,277.85
|
||||
2015-03-08,277.86
|
||||
2015-03-09,292.7
|
||||
2015-03-10,300.04
|
||||
2015-03-11,297.39
|
||||
2015-03-12,297.09
|
||||
2015-03-13,294.5
|
||||
2015-03-14,286.34
|
||||
2015-03-15,286.53
|
||||
2015-03-16,294.11
|
||||
2015-03-17,292.37
|
||||
2015-03-18,285.34
|
||||
2015-03-19,264.24
|
||||
2015-03-20,264.85
|
||||
2015-03-21,262.2
|
||||
2015-03-22,269.75
|
||||
2015-03-23,277.3
|
||||
2015-03-24,267
|
||||
2015-03-25,249.19
|
||||
2015-03-26,254.35
|
||||
2015-03-27,256.81
|
||||
2015-03-28,254.21
|
||||
2015-03-29,253.14
|
||||
2015-03-30,249.24
|
||||
2015-03-31,248.73
|
||||
2015-04-01,247.54
|
||||
2015-04-02,254.46
|
||||
2015-04-03,256.04
|
||||
2015-04-04,255.26
|
||||
2015-04-05,260.68
|
||||
2015-04-06,261.8
|
||||
2015-04-07,255.81
|
||||
2015-04-08,253.85
|
||||
2015-04-09,246.12
|
||||
2015-04-10,243.69
|
||||
2015-04-11,239.54
|
||||
2015-04-12,237.73
|
||||
2015-04-13,236.94
|
||||
2015-04-14,224.98
|
||||
2015-04-15,223.83
|
||||
2015-04-16,229.67
|
||||
2015-04-17,228.91
|
||||
2015-04-18,224.32
|
||||
2015-04-19,226.35
|
||||
2015-04-20,226.35
|
||||
2015-04-21,235.27
|
||||
2015-04-22,237.91
|
||||
2015-04-23,236.47
|
||||
2015-04-24,236.31
|
||||
2015-04-25,232.56
|
||||
2015-04-26,226.94
|
||||
2015-04-27,233.31
|
||||
2015-04-28,229.5
|
||||
2015-04-29,227.04
|
||||
2015-04-30,239.56
|
||||
2015-05-01,238.97
|
||||
2015-05-02,235.73
|
||||
2015-05-03,243.24
|
||||
2015-05-04,242.64
|
||||
2015-05-05,239.2
|
||||
2015-05-06,236.45
|
||||
2015-05-07,239.1
|
||||
2015-05-08,246.28
|
||||
2015-05-09,247.8
|
||||
2015-05-10,244.07
|
||||
2015-05-11,244.27
|
||||
2015-05-12,242.88
|
||||
2015-05-13,243.7
|
||||
2015-05-14,237.8
|
||||
2015-05-15,238.75
|
||||
2015-05-16,237.7
|
||||
2015-05-17,238.03
|
||||
2015-05-18,237.21
|
||||
2015-05-19,234.15
|
||||
2015-05-20,234.68
|
||||
2015-05-21,236.24
|
||||
2015-05-22,240.97
|
||||
2015-05-23,241.03
|
||||
2015-05-24,241.98
|
||||
2015-05-25,241.02
|
||||
2015-05-26,238.24
|
||||
2015-05-27,238.64
|
||||
2015-05-28,237.82
|
||||
2015-05-29,237.52
|
||||
2015-05-30,237.09
|
||||
2015-05-31,233.25
|
||||
2015-06-01,231.71
|
||||
2015-06-02,226.42
|
||||
2015-06-03,227.4
|
||||
2015-06-04,226.58
|
||||
2015-06-05,225.97
|
||||
2015-06-06,225.72
|
||||
2015-06-07,226.19
|
||||
2015-06-08,229.46
|
||||
2015-06-09,230.95
|
||||
2015-06-10,229.78
|
||||
2015-06-11,230.29
|
||||
2015-06-12,231.06
|
||||
2015-06-13,232.65
|
||||
2015-06-14,234.86
|
||||
2015-06-15,237.84
|
||||
2015-06-16,251.74
|
||||
2015-06-17,256.85
|
||||
2015-06-18,252.11
|
||||
2015-06-19,250.98
|
||||
2015-06-20,245.83
|
||||
2015-06-21,245.22
|
||||
2015-06-22,247.92
|
||||
2015-06-23,247.3
|
||||
2015-06-24,244.34
|
||||
2015-06-25,243.33
|
||||
2015-06-26,243.75
|
||||
2015-06-27,251.34
|
||||
2015-06-28,251.17
|
||||
2015-06-29,257.17
|
||||
2015-06-30,267.87
|
||||
2015-07-01,265.17
|
||||
2015-07-02,261.63
|
||||
2015-07-03,257.08
|
||||
2015-07-04,261.46
|
||||
2015-07-05,274.51
|
||||
2015-07-06,277.42
|
||||
2015-07-07,271.34
|
||||
2015-07-08,272.97
|
||||
2015-07-09,272.33
|
||||
2015-07-10,294.59
|
||||
2015-07-11,298.51
|
||||
2015-07-12,314.39
|
||||
2015-07-13,310.95
|
||||
2015-07-14,296.15
|
||||
2015-07-15,293.25
|
||||
2015-07-16,291.18
|
||||
2015-07-17,280.28
|
||||
2015-07-18,282.53
|
||||
2015-07-19,275.67
|
||||
2015-07-20,278.98
|
||||
2015-07-21,280.55
|
||||
2015-07-22,277.67
|
||||
2015-07-23,278.11
|
||||
2015-07-24,289.25
|
||||
2015-07-25,290.73
|
||||
2015-07-26,293.05
|
||||
2015-07-27,297.77
|
||||
2015-07-28,296.65
|
||||
2015-07-29,294.54
|
||||
2015-07-30,290.13
|
||||
2015-07-31,288.96
|
||||
2015-08-01,284.93
|
||||
2015-08-02,283.03
|
||||
2015-08-03,285.47
|
||||
2015-08-04,285.71
|
||||
2015-08-05,285.5
|
||||
2015-08-06,281.91
|
||||
2015-08-07,280.39
|
||||
2015-08-08,279.93
|
||||
2015-08-09,267
|
||||
2015-08-10,267.03
|
||||
2015-08-11,270.39
|
||||
2015-08-12,270.67
|
||||
2015-08-13,266.23
|
||||
2015-08-14,267.47
|
||||
2015-08-15,266.67
|
||||
2015-08-16,262.44
|
||||
2015-08-17,260.5
|
||||
2015-08-18,257.99
|
||||
2015-08-19,237.41
|
||||
2015-08-20,237.37
|
||||
2015-08-21,236.43
|
||||
2015-08-22,234.96
|
||||
2015-08-23,232.71
|
||||
2015-08-24,228.14
|
||||
2015-08-25,226.32
|
||||
2015-08-26,231.18
|
||||
2015-08-27,228.64
|
||||
2015-08-28,235.22
|
||||
2015-08-29,233.22
|
||||
2015-08-30,232.07
|
||||
2015-08-31,231.96
|
||||
2015-09-01,231.22
|
||||
2015-09-02,230.58
|
||||
2015-09-03,229.6
|
||||
2015-09-04,230.9
|
||||
2015-09-05,236.14
|
||||
2015-09-06,242.91
|
||||
2015-09-07,242.11
|
||||
2015-09-08,245.78
|
||||
2015-09-09,244.42
|
||||
2015-09-10,241.29
|
||||
2015-09-11,241.17
|
||||
2015-09-12,240.12
|
||||
2015-09-13,235.94
|
||||
2015-09-14,232.44
|
||||
2015-09-15,259.18
|
||||
2015-09-16,231.22
|
||||
2015-09-17,230.28
|
||||
2015-09-18,234.35
|
||||
2015-09-19,233.21
|
||||
2015-09-20,232.37
|
||||
2015-09-21,231.22
|
||||
2015-09-22,232.39
|
||||
2015-09-23,231.84
|
||||
2015-09-24,235.65
|
||||
2015-09-25,237.43
|
||||
2015-09-26,235.4
|
||||
2015-09-27,234.53
|
||||
2015-09-28,239.34
|
||||
2015-09-29,239.8
|
||||
2015-09-30,237.73
|
||||
2015-10-01,238.44
|
||||
2015-10-02,238.54
|
||||
2015-10-03,239.31
|
||||
2015-10-04,238.97
|
||||
2015-10-05,240.38
|
||||
2015-10-06,246.94
|
||||
2015-10-07,246.68
|
||||
2015-10-08,244.25
|
||||
2015-10-09,244.23
|
||||
2015-10-10,245.32
|
||||
2015-10-11,247.24
|
||||
2015-10-12,247.45
|
||||
2015-10-13,250.24
|
||||
2015-10-14,254.28
|
||||
2015-10-15,255.96
|
||||
2015-10-16,266.13
|
||||
2015-10-17,273.58
|
||||
2015-10-18,271.67
|
||||
2015-10-19,264.82
|
||||
2015-10-20,270.83
|
||||
2015-10-21,270.77
|
||||
2015-10-22,276.51
|
||||
2015-10-23,278.68
|
||||
2015-10-24,281.71
|
||||
2015-10-25,294.06
|
||||
2015-10-26,285.3
|
||||
2015-10-27,296.21
|
||||
2015-10-28,306.33
|
||||
2015-10-29,318.17
|
||||
2015-10-30,334.17
|
||||
2015-10-31,332.78
|
||||
2015-11-01,327.47
|
||||
2015-11-02,365.36
|
||||
2015-11-03,417.9
|
||||
2015-11-04,495.56
|
||||
2015-11-05,447.56
|
||||
2015-11-06,395.84
|
||||
2015-11-07,390.59
|
||||
2015-11-08,389.89
|
||||
2015-11-09,385.28
|
||||
2015-11-10,381.39
|
||||
2015-11-11,340.58
|
||||
2015-11-12,345.08
|
||||
2015-11-13,340.91
|
||||
2015-11-14,338.18
|
||||
2015-11-15,334.66
|
||||
2015-11-16,331.63
|
||||
2015-11-17,338.35
|
||||
2015-11-18,336.53
|
||||
2015-11-19,335.33
|
||||
2015-11-20,326.47
|
||||
2015-11-21,328.16
|
||||
2015-11-22,327.01
|
||||
2015-11-23,325.12
|
||||
2015-11-24,323.06
|
||||
2015-11-25,329.13
|
||||
2015-11-26,366.76
|
||||
2015-11-27,363.59
|
||||
2015-11-28,359.54
|
||||
2015-11-29,371.94
|
||||
2015-11-30,382.36
|
||||
2015-12-01,378.93
|
||||
2015-12-02,362.23
|
||||
2015-12-03,370.27
|
||||
2015-12-04,363.52
|
||||
2015-12-05,389.79
|
||||
2015-12-06,402.81
|
||||
2015-12-07,399.97
|
||||
2015-12-08,415.56
|
||||
2015-12-09,423.12
|
||||
2015-12-10,419.51
|
||||
2015-12-11,451.94
|
||||
2015-12-12,469.1
|
||||
2015-12-13,441.68
|
||||
2015-12-14,447.14
|
||||
2015-12-15,465.32
|
||||
2015-12-16,465.21
|
||||
2015-12-17,457.86
|
||||
2015-12-18,465.18
|
||||
2015-12-19,465.58
|
||||
2015-12-20,462.64
|
||||
2015-12-21,444.73
|
||||
2015-12-22,443.69
|
||||
2015-12-23,444.53
|
||||
2015-12-24,458.46
|
||||
2015-12-25,458.31
|
||||
2015-12-26,457.49
|
||||
2015-12-27,424.01
|
||||
2015-12-28,429.77
|
||||
2015-12-29,432.98
|
||||
2015-12-30,434.39
|
||||
2015-12-31,432.92
|
||||
|
15
ReactTool/frontend/src/components/data/BarGraph.csv
Normal file
@@ -0,0 +1,15 @@
|
||||
Country,Speed
|
||||
Australia,79.24
|
||||
China,78.61
|
||||
Hong Kong,43.88
|
||||
India,13.45
|
||||
Indonesia,16.16
|
||||
Japan,40.51
|
||||
Malaysia,23.74
|
||||
New Zealand,92.05
|
||||
Singapore,68.32
|
||||
South Korea,98.93
|
||||
Sri Lanka,12.60
|
||||
Taiwan,51.67
|
||||
Thailand,31.38
|
||||
Vietnam,35.33
|
||||
|
12
ReactTool/frontend/src/components/data/BubbleChart.csv
Normal file
@@ -0,0 +1,12 @@
|
||||
City,Length,NumberofStations,Ridership
|
||||
Delhi,230,348.12,1.7
|
||||
Guangzhow,247,531.1,2.4
|
||||
Tokyo,249,316.3,3.6
|
||||
Mexico City,163,200.9,0.93
|
||||
Moscow,198,412.1,1.6
|
||||
London,317,439.2,0.335
|
||||
Seoul,436,547.9,2.7
|
||||
Paris,304,219.9,2.3
|
||||
Beijing,342,727,0.75
|
||||
Shanghai,369,743,2.8
|
||||
N.Y.C.,458,443.7,0.67
|
||||
|
52
ReactTool/frontend/src/components/data/Choropleth.csv
Normal file
@@ -0,0 +1,52 @@
|
||||
state,value,code,id
|
||||
Nebraska,4.2,NE,31
|
||||
South Dakota,4.6,SD,46
|
||||
Utah,4.7,UT,49
|
||||
North Dakota,5.1,ND,38
|
||||
Iowa,5.3,IA,19
|
||||
Idaho,5.4,ID,16
|
||||
Maine,5.4,ME,23
|
||||
Vermont,5.6,VT,50
|
||||
Wyoming,5.8,WY,56
|
||||
Alabama,5.9,AL,01
|
||||
Kansas,5.9,KS,20
|
||||
Montana,5.9,MT,30
|
||||
Arkansas,6.1,AR,05
|
||||
Missouri,6.1,MO,29
|
||||
Oklahoma,6.1,OK,40
|
||||
Minnesota,6.2,MN,27
|
||||
South Carolina,6.2,SC,45
|
||||
Virginia,6.2,VA,51
|
||||
Wisconsin,6.3,WI,55
|
||||
Georgia,6.5,GA,13
|
||||
Kentucky,6.6,KY,21
|
||||
New Hampshire,6.7,NH,33
|
||||
Maryland,6.8,MD,24
|
||||
Indiana,7.1,IN,18
|
||||
Colorado,7.3,CO,08
|
||||
North Carolina,7.3,NC,37
|
||||
Tennessee,7.5,TN,47
|
||||
Oregon,7.6,OR,41
|
||||
Texas,7.6,TX,48
|
||||
Florida,7.7,FL,12
|
||||
Alaska,7.8,AK,02
|
||||
Delaware,7.8,DE,10
|
||||
Arizona,7.9,AZ,04
|
||||
Connecticut,7.9,CT,09
|
||||
District of Columbia,8,DC,11
|
||||
Mississippi,8.1,MS,28
|
||||
Ohio,8.1,OH,39
|
||||
Louisiana,8.3,LA,22
|
||||
West Virginia,8.3,WV,54
|
||||
New Mexico,8.4,NM,35
|
||||
Washington,8.4,WA,53
|
||||
Massachusetts,8.9,MA,25
|
||||
Pennsylvania,9.1,PN,42
|
||||
Rhode Island,9.4,RI,44
|
||||
Illinois,9.5,IL,17
|
||||
New Jersey,9.8,NJ,34
|
||||
Michigan,9.9,MI,26
|
||||
New York,10,NY,36
|
||||
California,10.1,CA,06
|
||||
Hawaii,11.6,HI,15
|
||||
Nevada,12.8,NV,32
|
||||
|
1374
ReactTool/frontend/src/components/data/Histogram-3-2.csv
Normal file
1374
ReactTool/frontend/src/components/data/Histogram.csv
Normal file
BIN
ReactTool/frontend/src/components/data/Images/1.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
ReactTool/frontend/src/components/data/Images/10.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
ReactTool/frontend/src/components/data/Images/11.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
ReactTool/frontend/src/components/data/Images/12.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
ReactTool/frontend/src/components/data/Images/2.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
ReactTool/frontend/src/components/data/Images/3.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
ReactTool/frontend/src/components/data/Images/4.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
ReactTool/frontend/src/components/data/Images/5.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
ReactTool/frontend/src/components/data/Images/6.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
ReactTool/frontend/src/components/data/Images/7.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
ReactTool/frontend/src/components/data/Images/8.png
Normal file
|
After Width: | Height: | Size: 101 KiB |
BIN
ReactTool/frontend/src/components/data/Images/9.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
ReactTool/frontend/src/components/data/Images/RightAns.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
ReactTool/frontend/src/components/data/Images/WrongAns.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
ReactTool/frontend/src/components/data/Images/skip.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
13
ReactTool/frontend/src/components/data/LineChart.csv
Normal file
@@ -0,0 +1,13 @@
|
||||
Month,Price
|
||||
Jan-2020,57.52
|
||||
Feb-2020,50.54
|
||||
Mar-2020,29.21
|
||||
Apr-2020,16.55
|
||||
May-2020,28.56
|
||||
Jun-2020,38.31
|
||||
Jul-2020,40.71
|
||||
Aug-2020,42.34
|
||||
Sep-2020,39.63
|
||||
Oct-2020,39.4
|
||||
Nov-2020,40.94
|
||||
Dec-2020,47.02
|
||||
|
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/AreaChart.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/BarChart.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/BubbleChart.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/Choropleth.png
Normal file
|
After Width: | Height: | Size: 678 KiB |
|
After Width: | Height: | Size: 599 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/Histogram.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/LineChart.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/PieChart.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/Scatterplot.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/Stacked100.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/StackedArea.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/StackedBar.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
ReactTool/frontend/src/components/data/Mini-VLAT/TreeMap.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
7
ReactTool/frontend/src/components/data/PieChart.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
Brand,Share
|
||||
Samsung,25
|
||||
Xiaomi,16
|
||||
Apple,15
|
||||
Oppo,10
|
||||
Vivo,10
|
||||
Others,24
|
||||
|
86
ReactTool/frontend/src/components/data/Scatterplot.csv
Normal file
@@ -0,0 +1,86 @@
|
||||
Height,Weight
|
||||
65.78331,112.9925
|
||||
71.51521,136.4873
|
||||
69.39874,153.0269
|
||||
68.2166,142.3354
|
||||
67.78781,144.2971
|
||||
68.69784,123.3024
|
||||
69.80204,141.4947
|
||||
70.01472,136.4623
|
||||
67.90265,112.3723
|
||||
66.78236,120.6672
|
||||
66.48769,127.4516
|
||||
67.62333,114.143
|
||||
68.30248,125.6107
|
||||
67.11656,122.4618
|
||||
68.27967,116.0866
|
||||
71.0916,139.9975
|
||||
66.461,129.5023
|
||||
68.64927,142.9733
|
||||
71.23033,137.9025
|
||||
67.13118,124.0449
|
||||
67.83379,141.2807
|
||||
68.87881,143.5392
|
||||
63.48115,97.90191
|
||||
68.42187,129.5027
|
||||
67.62804,141.8501
|
||||
67.20864,129.7244
|
||||
70.84235,142.4235
|
||||
67.49434,131.5502
|
||||
66.53401,108.3324
|
||||
65.44098,113.8922
|
||||
69.5233,103.3016
|
||||
65.8132,120.7536
|
||||
67.8163,125.7886
|
||||
70.59505,136.2225
|
||||
71.80484,140.1015
|
||||
69.20613,128.7487
|
||||
66.80368,141.7994
|
||||
67.65893,121.2319
|
||||
67.80701,131.3478
|
||||
64.04535,106.7115
|
||||
68.57463,124.3598
|
||||
65.18357,124.8591
|
||||
69.65814,139.6711
|
||||
67.96731,137.3696
|
||||
65.98088,106.4499
|
||||
68.67249,128.7639
|
||||
66.88088,145.6837
|
||||
67.69868,116.819
|
||||
69.82117,143.6215
|
||||
69.08817,134.9325
|
||||
69.91479,147.0219
|
||||
67.33182,126.3285
|
||||
70.26939,125.4839
|
||||
69.10344,115.7084
|
||||
65.38356,123.4892
|
||||
70.18447,147.8926
|
||||
70.40617,155.8987
|
||||
66.54376,128.0742
|
||||
66.36418,119.3701
|
||||
67.537,133.8148
|
||||
66.50418,128.7325
|
||||
68.99958,137.5453
|
||||
68.30355,129.7604
|
||||
67.01255,128.824
|
||||
70.80592,135.3165
|
||||
68.21951,109.6113
|
||||
69.05914,142.4684
|
||||
67.73103,132.749
|
||||
67.21568,103.5275
|
||||
67.36763,124.7299
|
||||
65.27033,129.3137
|
||||
70.84278,134.0175
|
||||
69.92442,140.3969
|
||||
64.28508,102.8351
|
||||
68.2452,128.5214
|
||||
66.35708,120.2991
|
||||
68.36275,138.6036
|
||||
65.4769,132.9574
|
||||
69.71947,115.6233
|
||||
67.72554,122.524
|
||||
68.63941,134.6254
|
||||
66.78405,121.8986
|
||||
70.05147,155.3767
|
||||
66.27848,128.9418
|
||||
69.20198,129.1013
|
||||
|
7
ReactTool/frontend/src/components/data/StackedArea.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
Year,Amelia,Isla,Olivia
|
||||
2009,3625,1908,5201
|
||||
2010,4227,2384,5279
|
||||
2011,5054,2849,4938
|
||||
2012,7061,3501,4585
|
||||
2013,5570,3526,4598
|
||||
2014,5327,4012,4724
|
||||
|
11
ReactTool/frontend/src/components/data/StackedBarGraph.csv
Normal file
@@ -0,0 +1,11 @@
|
||||
City,Sandwich,Water,Peanut,Soda,Vodka
|
||||
Helsinki,38.2,6.4,12.1,6.4,5.5
|
||||
Oslo,29.4,7.4,15.8,7.1,5.1
|
||||
Seoul,27.4,7.4,6.1,7.9,9.9
|
||||
Zurich,31.3,5.9,10.8,5.6,4.3
|
||||
Stockholm,28.4,4.1,11.3,4.9,5
|
||||
Paris,23.6,6.8,12.6,6.8,7.0
|
||||
N.Y.C.,24.2,3.9,16.8,3.9,7.1
|
||||
Singapore,19.4,5.2,14.8,6.6,6.2
|
||||
Toronto,20.8,5.4,18.2,3.4,8.0
|
||||
Copenhagen,24.3,2.8,10.8,5.0,3.7
|
||||
|
161
ReactTool/frontend/src/components/data/Treemap.json
Normal file
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"name": "Search/Portal",
|
||||
"children": [
|
||||
{
|
||||
"name": "Google",
|
||||
"group": "A",
|
||||
"value": 349758716,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "MSN/WindowsLive/Bing",
|
||||
"group": "A",
|
||||
"value": 271929865,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Yahoo!",
|
||||
"group": "C",
|
||||
"value": 233479611,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Ask",
|
||||
"group": "C",
|
||||
"value": 220410208,
|
||||
"colname": "level3"
|
||||
}
|
||||
],
|
||||
"colname": "level2"
|
||||
},
|
||||
{
|
||||
"name": "Social Network",
|
||||
"children": [
|
||||
{
|
||||
"name": "Facebook",
|
||||
"group": "C",
|
||||
"value": 218860914,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Twitter",
|
||||
"group": "A",
|
||||
"value": 42138681,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Orkut",
|
||||
"group": "B",
|
||||
"value": 28419073,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "LinkedIn",
|
||||
"group": "B",
|
||||
"value": 24389451,
|
||||
"colname": "level3"
|
||||
}
|
||||
],
|
||||
"colname": "level2"
|
||||
},
|
||||
{
|
||||
"name": "Software",
|
||||
"children": [
|
||||
{
|
||||
"name": "Mozilla",
|
||||
"group": "B",
|
||||
"value": 67949332,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Real Network",
|
||||
"group": "A",
|
||||
"value": 61513698,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Adobe",
|
||||
"group": "A",
|
||||
"value": 53002496,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Videolan",
|
||||
"group": "D",
|
||||
"value": 24850138,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Conduit",
|
||||
"group": "D",
|
||||
"value": 20610183,
|
||||
"colname": "level3"
|
||||
}
|
||||
],
|
||||
"colname": "level2"
|
||||
},
|
||||
{
|
||||
"name": "Retail",
|
||||
"children": [
|
||||
{
|
||||
"name": "eBay",
|
||||
"group": "B",
|
||||
"value": 121740943,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Amazon",
|
||||
"group": "A",
|
||||
"value": 111945278,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Wal-Mart",
|
||||
"group": "A",
|
||||
"value": 35538645,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Craigslist",
|
||||
"group": "D",
|
||||
"value": 35537183,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Target",
|
||||
"group": "D",
|
||||
"value": 23366341,
|
||||
"colname": "level3"
|
||||
}
|
||||
],
|
||||
"colname": "level2"
|
||||
},
|
||||
{
|
||||
"name": "Computer",
|
||||
"children": [
|
||||
{
|
||||
"name": "Apple",
|
||||
"group": "B",
|
||||
"value": 119232527,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "Dell",
|
||||
"group": "A",
|
||||
"value": 23324607,
|
||||
"colname": "level3"
|
||||
},
|
||||
{
|
||||
"name": "HP",
|
||||
"group": "A",
|
||||
"value": 20721035,
|
||||
"colname": "level3"
|
||||
}
|
||||
],
|
||||
"colname": "level2"
|
||||
}
|
||||
],
|
||||
"name": "CEO"
|
||||
}
|
||||
51502
ReactTool/frontend/src/components/data/USA.json
Normal file
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/AreaChart.png
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/BarGraph.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/BubbleChart.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/Choropleth.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/Histogram.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/LineChart.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/Pie.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/Scatterplot.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/StackedArea.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/StackedBar.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 30 KiB |
BIN
ReactTool/frontend/src/components/data/VLAT-Pics/TreeMap.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
86
ReactTool/frontend/src/components/data/scatter-2.csv
Normal file
@@ -0,0 +1,86 @@
|
||||
Height,Weight
|
||||
167.0812,51.25136008
|
||||
181.6608,61.91077208
|
||||
176.276,69.41318376
|
||||
173.2788,64.56428528
|
||||
172.1866,65.4533256
|
||||
174.498,55.9278936
|
||||
177.292,64.17873208
|
||||
177.8254,61.89716432
|
||||
172.466,50.97013304
|
||||
169.6212,54.73494664
|
||||
168.8846,57.8103004
|
||||
171.7548,51.77299088
|
||||
173.482,56.97569112
|
||||
170.4848,55.54687632
|
||||
173.4312,52.65749528
|
||||
180.5686,63.50288
|
||||
168.8084,58.740164
|
||||
174.371,64.85004824
|
||||
180.9242,62.5503368
|
||||
170.5102,56.26355168
|
||||
172.2882,64.08347776
|
||||
174.9552,65.10859568
|
||||
161.2392,44.4066568
|
||||
173.7868,58.740164
|
||||
171.7802,64.3420252
|
||||
170.7134,58.83995424
|
||||
179.9336,64.60057264
|
||||
171.4246,59.6700276
|
||||
168.9862,49.13762136
|
||||
166.2176,51.65959288
|
||||
176.5808,46.8560536
|
||||
167.1574,54.771234
|
||||
172.2628,57.05733768
|
||||
179.324,61.78830224
|
||||
182.372,63.5482392
|
||||
175.7934,58.39997
|
||||
169.672,64.3193456
|
||||
171.8564,54.98895816
|
||||
172.2374,59.5793092
|
||||
162.687,48.40280232
|
||||
174.1678,56.40870112
|
||||
165.5572,56.63549712
|
||||
176.9364,63.35319464
|
||||
172.6438,62.30993304
|
||||
167.5892,48.2848684
|
||||
174.4218,58.40450592
|
||||
169.8752,66.07928256
|
||||
171.958,52.98861744
|
||||
177.3428,65.14488304
|
||||
175.4886,61.20316856
|
||||
177.5714,66.68709584
|
||||
171.0182,57.30227736
|
||||
178.4858,56.91672416
|
||||
175.514,52.48513032
|
||||
166.0652,56.01407608
|
||||
178.2572,67.08172088
|
||||
178.8414,70.7149928
|
||||
169.0116,58.09152744
|
||||
168.5544,54.14527704
|
||||
171.5516,60.69514552
|
||||
168.91,58.39089816
|
||||
175.26,62.3915796
|
||||
173.482,58.85809792
|
||||
170.2054,58.43172144
|
||||
179.8574,61.38006944
|
||||
173.2788,49.71821912
|
||||
175.4124,64.62325224
|
||||
172.0342,60.214338
|
||||
170.7388,73.96037976
|
||||
171.1198,56.57653016
|
||||
165.7858,58.65398152
|
||||
179.9336,60.79039984
|
||||
177.5968,63.6843168
|
||||
163.2966,46.64740128
|
||||
173.355,58.29564384
|
||||
168.5544,54.5671176
|
||||
173.6344,62.8678512
|
||||
166.3192,60.30959232
|
||||
177.0888,52.44430704
|
||||
172.0342,55.57409184
|
||||
174.3456,61.06709096
|
||||
169.6212,55.2928648
|
||||
177.927,70.47912496
|
||||
168.3512,58.48615248
|
||||
175.768,58.5587272
|
||||
|
86
ReactTool/frontend/src/components/data/scatter.csv
Normal file
@@ -0,0 +1,86 @@
|
||||
height,weight,height(cm),weight(kg)
|
||||
65.78,112.99,167.0812,51.25136008
|
||||
71.52,136.49,181.6608,61.91077208
|
||||
69.4,153.03,176.276,69.41318376
|
||||
68.22,142.34,173.2788,64.56428528
|
||||
67.79,144.3,172.1866,65.4533256
|
||||
68.7,123.3,174.498,55.9278936
|
||||
69.8,141.49,177.292,64.17873208
|
||||
70.01,136.46,177.8254,61.89716432
|
||||
67.9,112.37,172.466,50.97013304
|
||||
66.78,120.67,169.6212,54.73494664
|
||||
66.49,127.45,168.8846,57.8103004
|
||||
67.62,114.14,171.7548,51.77299088
|
||||
68.3,125.61,173.482,56.97569112
|
||||
67.12,122.46,170.4848,55.54687632
|
||||
68.28,116.09,173.4312,52.65749528
|
||||
71.09,140,180.5686,63.50288
|
||||
66.46,129.5,168.8084,58.740164
|
||||
68.65,142.97,174.371,64.85004824
|
||||
71.23,137.9,180.9242,62.5503368
|
||||
67.13,124.04,170.5102,56.26355168
|
||||
67.83,141.28,172.2882,64.08347776
|
||||
68.88,143.54,174.9552,65.10859568
|
||||
63.48,97.9,161.2392,44.4066568
|
||||
68.42,129.5,173.7868,58.740164
|
||||
67.63,141.85,171.7802,64.3420252
|
||||
67.21,129.72,170.7134,58.83995424
|
||||
70.84,142.42,179.9336,64.60057264
|
||||
67.49,131.55,171.4246,59.6700276
|
||||
66.53,108.33,168.9862,49.13762136
|
||||
65.44,113.89,166.2176,51.65959288
|
||||
69.52,103.3,176.5808,46.8560536
|
||||
65.81,120.75,167.1574,54.771234
|
||||
67.82,125.79,172.2628,57.05733768
|
||||
70.6,136.22,179.324,61.78830224
|
||||
71.8,140.1,182.372,63.5482392
|
||||
69.21,128.75,175.7934,58.39997
|
||||
66.8,141.8,169.672,64.3193456
|
||||
67.66,121.23,171.8564,54.98895816
|
||||
67.81,131.35,172.2374,59.5793092
|
||||
64.05,106.71,162.687,48.40280232
|
||||
68.57,124.36,174.1678,56.40870112
|
||||
65.18,124.86,165.5572,56.63549712
|
||||
69.66,139.67,176.9364,63.35319464
|
||||
67.97,137.37,172.6438,62.30993304
|
||||
65.98,106.45,167.5892,48.2848684
|
||||
68.67,128.76,174.4218,58.40450592
|
||||
66.88,145.68,169.8752,66.07928256
|
||||
67.7,116.82,171.958,52.98861744
|
||||
69.82,143.62,177.3428,65.14488304
|
||||
69.09,134.93,175.4886,61.20316856
|
||||
69.91,147.02,177.5714,66.68709584
|
||||
67.33,126.33,171.0182,57.30227736
|
||||
70.27,125.48,178.4858,56.91672416
|
||||
69.1,115.71,175.514,52.48513032
|
||||
65.38,123.49,166.0652,56.01407608
|
||||
70.18,147.89,178.2572,67.08172088
|
||||
70.41,155.9,178.8414,70.7149928
|
||||
66.54,128.07,169.0116,58.09152744
|
||||
66.36,119.37,168.5544,54.14527704
|
||||
67.54,133.81,171.5516,60.69514552
|
||||
66.5,128.73,168.91,58.39089816
|
||||
69,137.55,175.26,62.3915796
|
||||
68.3,129.76,173.482,58.85809792
|
||||
67.01,128.82,170.2054,58.43172144
|
||||
70.81,135.32,179.8574,61.38006944
|
||||
68.22,109.61,173.2788,49.71821912
|
||||
69.06,142.47,175.4124,64.62325224
|
||||
67.73,132.75,172.0342,60.214338
|
||||
67.22,103.53,170.7388,46.96037976
|
||||
67.37,124.73,171.1198,56.57653016
|
||||
65.27,129.31,165.7858,58.65398152
|
||||
70.84,134.02,179.9336,60.79039984
|
||||
69.92,140.4,177.5968,63.6843168
|
||||
64.29,102.84,163.2966,46.64740128
|
||||
68.25,128.52,173.355,58.29564384
|
||||
66.36,120.3,168.5544,54.5671176
|
||||
68.36,138.6,173.6344,62.8678512
|
||||
65.48,132.96,166.3192,60.30959232
|
||||
69.72,115.62,177.0888,52.44430704
|
||||
67.73,122.52,172.0342,55.57409184
|
||||
68.64,134.63,174.3456,61.06709096
|
||||
66.78,121.9,169.6212,55.2928648
|
||||
70.05,155.38,177.927,70.47912496
|
||||
66.28,128.94,168.3512,58.48615248
|
||||
69.2,129.1,175.768,58.5587272
|
||||
|
1
ReactTool/frontend/src/components/data/us.json
Normal file
192
ReactTool/frontend/src/components/histogram-mini.js
Normal file
@@ -0,0 +1,192 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/Histogram-3-2.csv';
|
||||
import img6 from '../components/data/Mini-VLAT/Histogram.png'
|
||||
|
||||
|
||||
|
||||
class HistogramMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://www.kaggle.com/arashnic/taxi-pricing-with-mobility-analytics
|
||||
//https://www.d3-graph-gallery.com/graph/histogram_basic.html
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Taxi Passenger Ratings").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.0 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.4 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img6).attr('height', 1.1 * height)
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
// svg.append("text").attr("class", 'bubbleTitle').text("Taxi Passenger Ratings").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.0 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
// var image = svg.append('image').attr('width', 1.4 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img6).attr('height', 1.1 * height)
|
||||
|
||||
d3.csv(data).then(function (data) {
|
||||
data.forEach(function (d) {
|
||||
d.Trip_Distance = parseFloat(d.Trip_Distance);
|
||||
})
|
||||
var x = d3.scaleLinear()
|
||||
.domain([d3.min(data, function (d) { return d.Trip_Distance }), 110]) // can use this instead of 1000 to have the max of data: d3.max(data, function(d) { return +d.price })
|
||||
.range([0, width]);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(d3.axisBottom(x))
|
||||
//.style("font-size", 1.3*(length/margin.top));
|
||||
|
||||
var histogram = d3.histogram()
|
||||
.value(function (d) {
|
||||
return d.Trip_Distance;
|
||||
}) // I need to give the vector of value
|
||||
.domain(x.domain()) // then the domain of the graphic
|
||||
.thresholds(x.ticks(10)); // then the numbers of bins
|
||||
|
||||
var bins = histogram(data);
|
||||
|
||||
var y = d3.scaleLinear()
|
||||
.range([height, 0]);
|
||||
y.domain([0, 260]); // d3.hist has to be called before the Y axis obviously
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y-axis")
|
||||
.call(d3.axisLeft(y))
|
||||
//.style("font-size", 1.3*(length/margin.top));
|
||||
|
||||
function make_y_axis() {
|
||||
return d3.axisLeft(y).ticks(11).tickSizeInner(-width + margin.left + margin.right);
|
||||
}
|
||||
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_axis()
|
||||
.tickSize(-width, 0, 0)
|
||||
.tickFormat("")
|
||||
.tickSizeOuter(0)
|
||||
)
|
||||
|
||||
// append the bar rectangles to the svg element
|
||||
svg.selectAll("rect")
|
||||
.data(bins)
|
||||
.enter()
|
||||
.append("rect")
|
||||
.attr("x", 1)
|
||||
.attr("transform", function (d) {
|
||||
return "translate(" + x(d.x0) + "," + y(d.length) + ")";
|
||||
})
|
||||
.attr("width", function (d) {
|
||||
return x(d.x1) - x(d.x0);
|
||||
})
|
||||
.attr("height", function (d) {
|
||||
return height - y(d.length);
|
||||
})
|
||||
.style("fill", "#3182bd")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return -1.4 * margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else if (width < 400) {
|
||||
return -1.7 * margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Number of Customers")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("transform", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.3 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else if (width < 400) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.5 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.1 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
})
|
||||
.style("text-anchor", "middle")
|
||||
.style("font-weight", "bold")
|
||||
.text("Distance (in Km)")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", width / 3)
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Trip Distance and Customers")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default HistogramMini;
|
||||
254
ReactTool/frontend/src/components/linechart-mini.js
Normal file
@@ -0,0 +1,254 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import img12 from '../components/data/Mini-VLAT/LineChart.png';
|
||||
|
||||
|
||||
class LineChartMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://www.eia.gov/dnav/pet/hist/LeafHandler.ashx?n=PET&s=RWTC&f=M
|
||||
//https://www.d3-graph-gallery.com/line
|
||||
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Monthly Oil Price History in 2015").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img12).attr('height', 1.1 * height)
|
||||
|
||||
}
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
// svg.append("text").attr("class", 'bubbleTitle').text("Monthly Oil Price History in 2015").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
// var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img12).attr('height', 1.1 * height)
|
||||
|
||||
var data = [57.52, 50.54, 29.21, 16.55, 28.56, 38.31, 40.71, 42.34, 39.63, 39.4, 40.94, 47.02]
|
||||
|
||||
|
||||
var xScale = d3.scaleTime()
|
||||
.domain([new Date(2020, 0, 1), new Date(2020, 11, 31)]).range([0, width])
|
||||
|
||||
svg.append("g")
|
||||
//.attr("class", "axis")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(xScale).tickFormat(d3.timeFormat("%B")))
|
||||
/*
|
||||
.style("font-size", function() {
|
||||
if (length < 700){
|
||||
return (length/margin.top)
|
||||
}
|
||||
else {
|
||||
return 1.3*(length/margin.top)
|
||||
}
|
||||
}) */
|
||||
.selectAll("text")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", function () {
|
||||
if (width < 500) {
|
||||
return "rotate(25)"
|
||||
}
|
||||
else {
|
||||
return "rotate(15)"
|
||||
}
|
||||
})
|
||||
.attr("x", function () {
|
||||
if (length < 900) {
|
||||
return 2 * length / margin.right
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 950 && width > 400) {
|
||||
return (2.5) * length / margin.right
|
||||
}
|
||||
else if (width < 400) {
|
||||
return (1.5) * length / margin.right
|
||||
}
|
||||
})
|
||||
.attr("dy", function () {
|
||||
return "0.3em"
|
||||
})
|
||||
|
||||
|
||||
// Add Y axis
|
||||
var yScale = d3.scaleLinear()
|
||||
.domain([0, 60])
|
||||
.range([height, 0]);
|
||||
|
||||
svg.append("g")
|
||||
//.attr("class", "axis")
|
||||
.call(d3.axisLeft(yScale))
|
||||
.selectAll("text")
|
||||
.attr("class", "y-axis");
|
||||
|
||||
var x = d3.scaleLinear().domain([0, data.length]).range([0, width]);
|
||||
var y = d3.scaleLinear().domain([0, 60]).range([height, 0]);
|
||||
var line = d3.line()
|
||||
.x(function (d, i) {
|
||||
return x(i);
|
||||
})
|
||||
.y(function (d) {
|
||||
return y(d);
|
||||
})
|
||||
|
||||
// Add the line
|
||||
svg.append("path")
|
||||
.datum(data)
|
||||
.attr("fill", "none")
|
||||
.attr("stroke", "#3182bd")
|
||||
.attr("stroke-width", function () {
|
||||
if (length < 700) {
|
||||
return 1.5
|
||||
}
|
||||
else {
|
||||
return 2.5
|
||||
}
|
||||
})
|
||||
.attr("d", line(data));
|
||||
|
||||
function make_x_gridlines() {
|
||||
return d3.axisBottom(xScale)
|
||||
.ticks(11)
|
||||
}
|
||||
|
||||
// gridlines in y axis function
|
||||
function make_y_gridlines() {
|
||||
return d3.axisLeft(yScale)
|
||||
.ticks(11)
|
||||
}
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(make_x_gridlines()
|
||||
.tickSize(-height)
|
||||
.tickFormat("")
|
||||
)
|
||||
|
||||
// add the Y gridlines
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_gridlines()
|
||||
.tickSize(-width)
|
||||
.tickFormat("")
|
||||
)
|
||||
|
||||
svg.selectAll("myCircles")
|
||||
.data(data)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("fill", "#3182bd")
|
||||
.attr("stroke", "none")
|
||||
.attr("cx", function (d, i) { return x(i) })
|
||||
.attr("cy", function (d) { return y(d) })
|
||||
.attr("r", function () {
|
||||
if (length < 700) {
|
||||
return "2";
|
||||
}
|
||||
else {
|
||||
return "4"
|
||||
}
|
||||
})
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return 0 - margin.left + (margin.top / 5.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else if (width < 400) {
|
||||
return 0 - margin.left + (margin.top / 8.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return 0 - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", 0 - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Oil Price ($)")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", width / 2.5)
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Oil Prices in 2020")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("transform", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.6 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else if (width < 400) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.6 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.1 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
})
|
||||
.style("text-anchor", "middle")
|
||||
.style("font-weight", "bold")
|
||||
.text("Month")
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default LineChartMini;
|
||||
147
ReactTool/frontend/src/components/pieChart-mini.js
Normal file
@@ -0,0 +1,147 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/Histogram.csv';
|
||||
import img11 from '../components/data/Mini-VLAT/PieChart.png'
|
||||
|
||||
|
||||
|
||||
class PieChartMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://www.gartner.com/en/newsroom/press-releases/2021-09-01-2q21-smartphone-market-share
|
||||
//https://www.d3-graph-gallery.com/pie
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Global Smartphone Market Share (%)").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img11).attr('height', 1.1 * height)
|
||||
}
|
||||
|
||||
else {
|
||||
//var e = document.getElementById("graph_box");
|
||||
var width = e.clientWidth, height = e.clientHeight, margin = width / 5;
|
||||
|
||||
var radius = Math.min(width, height) / 2 - margin;
|
||||
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${width / 2}, ${height / 2})`);
|
||||
|
||||
var data = { Samsung: 17.6, Xiaomi: 15.5, Apple: 15.0, Oppo: 10.2, Vivo: 9.8, Others: 31.9 }
|
||||
|
||||
const color = d3.scaleOrdinal()
|
||||
.range(['#0868ac', '#f03b20', '#feb24c', '#78c679', '#ffffb2', '#756bb1'])
|
||||
|
||||
const pie = d3.pie()
|
||||
.value(function (d) {
|
||||
return d[1]
|
||||
})
|
||||
|
||||
const data_ready = pie(Object.entries(data))
|
||||
|
||||
const arcGenerator = d3.arc()
|
||||
.innerRadius(0)
|
||||
.outerRadius(function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return 1.2 * radius;
|
||||
}
|
||||
else if (width < 400) {
|
||||
return 3.5 * radius
|
||||
}
|
||||
else {
|
||||
return radius;
|
||||
}
|
||||
})
|
||||
|
||||
svg
|
||||
.selectAll('mySlices')
|
||||
.data(data_ready)
|
||||
.join('path')
|
||||
.attr('d', arcGenerator)
|
||||
.attr('fill', function (d) {
|
||||
return (color(d.data[0]))
|
||||
})
|
||||
.attr("stroke", "black")
|
||||
.style("stroke-width", "0px")
|
||||
.style("opacity", 0.7)
|
||||
|
||||
// Now add the annotation. Use the centroid method to get the best coordinates
|
||||
svg
|
||||
.selectAll('mySlices')
|
||||
.data(data_ready)
|
||||
.join('text')
|
||||
.text(function (d) {
|
||||
return d.data[0]
|
||||
})
|
||||
.attr("transform", function (d) {
|
||||
return `translate(${arcGenerator.centroid(d)})`
|
||||
})
|
||||
.style("fill", "#252525")
|
||||
.style("text-anchor", "middle")
|
||||
.style('font-weight', "bold")
|
||||
.attr("class", "x-label")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", -width / 5.5)
|
||||
.attr("y", -width / 3) // +20 to adjust position (lower)
|
||||
.text("Global Smartphone Market Share in 2021")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PieChartMini;
|
||||
|
||||
|
||||
function pieChart() {
|
||||
|
||||
|
||||
}
|
||||
233
ReactTool/frontend/src/components/quiz.js
Normal file
@@ -0,0 +1,233 @@
|
||||
const questions = [
|
||||
{
|
||||
question: "What was the price range of a barrel of oil in 2020?",
|
||||
optionA: "$16.55 - $57.52",
|
||||
optionB: "$19.52 - $59.00",
|
||||
optionC: "$23.43 - $60.72",
|
||||
optionD: "$21.82 - $87.52",
|
||||
correctOption: "optionA",
|
||||
},
|
||||
|
||||
{
|
||||
question: "What is the range of the average internet speed in Asia?",
|
||||
optionA: "5.50Mbps - 30.60Mbps",
|
||||
optionB: "7.00Mbps - 29.40Mbps",
|
||||
optionC: "6.40Mbps - 27.38Mbps",
|
||||
optionD: "5.50Mbps - 28.60Mbps",
|
||||
correctOption: "optionD",
|
||||
},
|
||||
{
|
||||
question: "What is the cost of peanuts in Las Vegas?",
|
||||
optionA: "$9.0",
|
||||
optionB: "$6.1",
|
||||
optionC: "$10.3",
|
||||
optionD: "$4.3",
|
||||
correctOption: "optionB",
|
||||
},
|
||||
|
||||
{
|
||||
question: "What is the approval rating of Republicans among the people who have the education level of Postgraduate Study?",
|
||||
optionA: "35%",
|
||||
optionB: "27%",
|
||||
optionC: "23%",
|
||||
optionD: "20%",
|
||||
correctOption: "optionB",
|
||||
},
|
||||
|
||||
{
|
||||
question: "About what is the global smartphone market share of Samsung?",
|
||||
optionA: "20%",
|
||||
optionB: "25%",
|
||||
optionC: "30%",
|
||||
optionD: "15%",
|
||||
correctOption: "optionB",
|
||||
},
|
||||
|
||||
{
|
||||
question: "How many people have rated the taxi between 4.2 and 4.4?",
|
||||
optionA: "270",
|
||||
optionB: "190",
|
||||
optionC: "300",
|
||||
optionD: "290",
|
||||
correctOption: "optionB",
|
||||
},
|
||||
|
||||
{
|
||||
question: "There is a negative linear relationship between the height and the weight of the 85 males.",
|
||||
optionA: "True",
|
||||
optionB: "False",
|
||||
optionC: "",
|
||||
optionD: "",
|
||||
correctOption: "optionB",
|
||||
},
|
||||
|
||||
{
|
||||
question: "What was the average price of a pound of coffee beans in September 2013?",
|
||||
optionA: "$5.15",
|
||||
optionB: "$6.2",
|
||||
optionC: "$4.8",
|
||||
optionD: "$4.3",
|
||||
correctOption: "optionA",
|
||||
},
|
||||
|
||||
{
|
||||
question: "What was the number of girls named 'Olivia' in 2010 in the UK?",
|
||||
optionA: "2000",
|
||||
optionB: "2500",
|
||||
optionC: "1700",
|
||||
optionD: "2400",
|
||||
correctOption: "optionC",
|
||||
},
|
||||
|
||||
{
|
||||
question: "What is the total length of the metro system in Beijing?",
|
||||
optionA: "525 km",
|
||||
optionB: "495 km",
|
||||
optionC: "305 km",
|
||||
optionD: "475 km",
|
||||
correctOption: "optionA",
|
||||
},
|
||||
|
||||
{
|
||||
question: "In 2015, the unemployment rate for Washington (WA) was higher than that of Wisconsin (WI)",
|
||||
optionA: "True",
|
||||
optionB: "False",
|
||||
optionC: "",
|
||||
optionD: "",
|
||||
correctOption: "optionA",
|
||||
},
|
||||
|
||||
{
|
||||
question: "For which website was the number of unique visitors the largest in 2010?",
|
||||
optionA: "Amazon",
|
||||
optionB: "Chase",
|
||||
optionC: "PayPal",
|
||||
optionD: "Citibank",
|
||||
correctOption: "optionD",
|
||||
}
|
||||
|
||||
]
|
||||
var graph_box = document.getElementById('graph_box');
|
||||
var question = document.getElementById("question");
|
||||
var option1 = document.querySelector("#option1");
|
||||
var option2 = document.querySelector("#option2");
|
||||
var option3 = document.querySelector("#option3");
|
||||
var option4 = document.querySelector("#option4");
|
||||
var next = document.querySelector("#sub-button");
|
||||
var answers = document.querySelectorAll('.answer');
|
||||
var showScore = document.querySelector('#showScore');
|
||||
var cont = document.querySelector(".continue");
|
||||
var timeCount = document.querySelector(".timer");
|
||||
|
||||
var questionCount = 0;
|
||||
var score = 0;
|
||||
var counter;
|
||||
var loadQuestion = () => {
|
||||
var questionList = questions[questionCount];
|
||||
question.innerText = questionList.question;
|
||||
option1.innerText = questionList.optionA;
|
||||
option2.innerText = questionList.optionB;
|
||||
option3.innerText = questionList.optionC;
|
||||
option4.innerText = questionList.optionD;
|
||||
}
|
||||
loadQuestion();
|
||||
|
||||
|
||||
var checkAnswer = () => {
|
||||
var answer;
|
||||
answers.forEach((curAnsElem) => {
|
||||
if (curAnsElem.checked) {
|
||||
answer = curAnsElem.id;
|
||||
}
|
||||
})
|
||||
return answer;
|
||||
}
|
||||
|
||||
next.addEventListener('click', () => {
|
||||
var checkedAnswer = checkAnswer();
|
||||
console.log(checkedAnswer);
|
||||
|
||||
if (checkedAnswer === questions[questionCount].correctOption) {
|
||||
score++;
|
||||
console.log("Score:" + score);
|
||||
sessionStorage.setItem("scores", score)
|
||||
};
|
||||
|
||||
questionCount++;
|
||||
deSelectAll();
|
||||
|
||||
if (questionCount < questions.length) {
|
||||
|
||||
if (questionCount === 1) {
|
||||
BarChart();
|
||||
loadQuestion();
|
||||
}
|
||||
else if (questionCount === 2) {
|
||||
StackedBar();
|
||||
loadQuestion();
|
||||
}
|
||||
else if (questionCount === 3) {
|
||||
stacked100();
|
||||
loadQuestion();
|
||||
|
||||
}
|
||||
else if (questionCount === 4) {
|
||||
pieChart();
|
||||
loadQuestion();
|
||||
}
|
||||
else if (questionCount === 5) {
|
||||
histogram();
|
||||
loadQuestion();
|
||||
}
|
||||
else if (questionCount === 6) {
|
||||
scatterplot();
|
||||
loadQuestion();
|
||||
document.getElementById("optionC").disabled = true;
|
||||
document.getElementById("optionD").disabled = true;
|
||||
}
|
||||
else if (questionCount === 7) {
|
||||
areaChart();
|
||||
loadQuestion();
|
||||
document.getElementById("optionC").disabled = false;
|
||||
document.getElementById("optionD").disabled = false;
|
||||
}
|
||||
else if (questionCount === 8) {
|
||||
stackedArea();
|
||||
loadQuestion();
|
||||
document.getElementById("optionC").disabled = false;
|
||||
document.getElementById("optionD").disabled = false;
|
||||
}
|
||||
else if (questionCount === 9) {
|
||||
bubbleChart();
|
||||
loadQuestion();
|
||||
document.getElementById("optionC").disabled = false;
|
||||
document.getElementById("optionD").disabled = false;
|
||||
}
|
||||
else if (questionCount === 10) {
|
||||
choropleth();
|
||||
loadQuestion();
|
||||
document.getElementById("optionC").disabled = true;
|
||||
document.getElementById("optionD").disabled = true;
|
||||
}
|
||||
else if (questionCount === 11) {
|
||||
treemap();
|
||||
loadQuestion();
|
||||
document.getElementById("optionC").disabled = false;
|
||||
document.getElementById("optionD").disabled = false;
|
||||
}
|
||||
else {
|
||||
loadQuestion();
|
||||
}
|
||||
console.log(questionCount);
|
||||
}
|
||||
else {
|
||||
location.href = "score.html"
|
||||
}
|
||||
})
|
||||
|
||||
var deSelectAll = () => {
|
||||
answers.forEach((curAnsElem) => curAnsElem.checked = false);
|
||||
}
|
||||
if (questionCount === 0) {
|
||||
linechart();
|
||||
}
|
||||
181
ReactTool/frontend/src/components/scatterplot-mini.js
Normal file
@@ -0,0 +1,181 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/scatter-2.csv';
|
||||
import img1 from '../components/data/Mini-VLAT/Scatterplot.png'
|
||||
|
||||
|
||||
|
||||
class ScatterPlotMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//http://wiki.stat.ucla.edu/socr/index.php/SOCR_Data_Dinov_020108_HeightsWeights
|
||||
//https://www.d3-graph-gallery.com/graph/scatter_basic.html
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
|
||||
if (length < 570) {
|
||||
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Height and Weight of 85 Males").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img1).attr('height', 1.1 * height)
|
||||
}
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
|
||||
d3.csv(data).then(function (data) {
|
||||
data.forEach(function (d) {
|
||||
d.Height = parseFloat(d.Height);
|
||||
d.Weight = parseFloat(d.Weight);
|
||||
})
|
||||
const x = d3.scaleLinear()
|
||||
.domain([155, 190])
|
||||
.range([0, width]);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(x))
|
||||
|
||||
// Add Y axis
|
||||
const y = d3.scaleLinear()
|
||||
.domain([40, 75])
|
||||
.range([height, 0]);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y-axis")
|
||||
.call(d3.axisLeft(y))
|
||||
|
||||
|
||||
function make_x_gridlines() {
|
||||
return d3.axisBottom(x)
|
||||
.ticks(5)
|
||||
}
|
||||
|
||||
// gridlines in y axis function
|
||||
function make_y_gridlines() {
|
||||
return d3.axisLeft(y)
|
||||
.ticks(8)
|
||||
}
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(make_x_gridlines()
|
||||
.tickSize(-height)
|
||||
.tickFormat("")
|
||||
)
|
||||
|
||||
// add the Y gridlines
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_gridlines()
|
||||
.tickSize(-width)
|
||||
.tickFormat("")
|
||||
)
|
||||
// Add dots
|
||||
svg.append('g')
|
||||
.selectAll("dot")
|
||||
.data(data)
|
||||
.join("circle")
|
||||
.attr("cx", function (d) { return x(d.Height); })
|
||||
.attr("cy", function (d) { return y(d.Weight); })
|
||||
.attr("r", 3.0)
|
||||
.style("fill", "#3182bd")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width < 400) {
|
||||
return 0 - margin.left + (margin.top / 8.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return 0 - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", 0 - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Weight (kg)")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", width / 4)
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Weight and Height of 85 Individuals")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("transform", function () {
|
||||
if (width < 500) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.4 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.1 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
})
|
||||
.style("text-anchor", "middle")
|
||||
.style("font-weight", "bold")
|
||||
.text("Height (cm)")
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ScatterPlotMini;
|
||||
386
ReactTool/frontend/src/components/stacked100bar-mini.js
Normal file
@@ -0,0 +1,386 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/100StackedBarGraph.csv';
|
||||
import img5 from '../components/data/Mini-VLAT/Stacked100.png'
|
||||
|
||||
|
||||
|
||||
class StackedBarChartMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://olympics.com/en/olympic-games/tokyo-2020/medals
|
||||
//https://www.d3-graph-gallery.com/graph/barplot_stacked_percent.html
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Election Exit Poll of California State by Education Level").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img5).attr('height', 1.1 * height)
|
||||
}
|
||||
|
||||
else {
|
||||
//var e = document.getElementById("graph_box");
|
||||
//const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
d3.csv(data).then(function (data) {
|
||||
data.forEach(function (d) {
|
||||
d.Gold = parseFloat(d.Gold);
|
||||
d.Silver = parseFloat(d.Silver);
|
||||
d.Bronze = parseFloat(d.Bronze);
|
||||
d.Countries = d.Countries;
|
||||
})
|
||||
|
||||
var subgroups = data.columns.slice(1);
|
||||
|
||||
var groups = data.map(d => (d.Countries));
|
||||
|
||||
|
||||
var xScale = d3.scaleBand().domain(groups).range([0, width]).padding([0.2])
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(xScale).tickSizeOuter(0));
|
||||
|
||||
var yScale = d3.scaleLinear().domain([0, 100]).range([height, 0]);
|
||||
|
||||
svg.append("g").attr("class", "y-axis").call(d3.axisLeft(yScale));
|
||||
|
||||
const color = d3.scaleOrdinal()
|
||||
.domain(subgroups)
|
||||
.range(['#feb24c', '#bdbdbd', '#cd7f32'])
|
||||
|
||||
//stack the data? --> stack per subgroup
|
||||
const stackedData = d3.stack()
|
||||
.keys(subgroups)
|
||||
(data)
|
||||
|
||||
data.forEach(function (d) {
|
||||
// Compute the total
|
||||
var tot = 0
|
||||
for (var i in subgroups) {
|
||||
const n = subgroups[i];
|
||||
tot += +d[n]
|
||||
}
|
||||
// Now normalize
|
||||
for (i in subgroups) {
|
||||
const n = subgroups[i];
|
||||
d[n] = d[n] / tot * 100
|
||||
}
|
||||
})
|
||||
|
||||
function make_y_axis() {
|
||||
return d3.axisLeft(yScale).ticks(11).tickSizeInner(-width + margin.left + margin.right);
|
||||
}
|
||||
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_axis()
|
||||
.tickSize(-width, 0, 0)
|
||||
.tickFormat("")
|
||||
.tickSizeOuter(0)
|
||||
)
|
||||
svg.append("g")
|
||||
.selectAll("g")
|
||||
// Enter in the stack data = loop key per key = group per group
|
||||
.data(stackedData)
|
||||
.join("g")
|
||||
.attr("fill", d => color(d.key))
|
||||
.selectAll("rect")
|
||||
// enter a second time = loop subgroup per subgroup to add all rectangles
|
||||
.data(d => d)
|
||||
.join("rect")
|
||||
.attr("x", d => xScale(d.data.Countries) + length / 50)
|
||||
.attr("y", d => yScale(d[1]))
|
||||
.attr("height", d => yScale(d[0]) - yScale(d[1]))
|
||||
.attr("width", xScale.bandwidth() - length / 60)
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return 0 - margin.left + (margin.top / 7.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else if (width < 400) {
|
||||
return 0 - margin.left + (margin.top / 9.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return 0 - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", 0 - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Olympic Medals (%)")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("transform", function () {
|
||||
if (width < 500) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.5 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.1 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
})
|
||||
.style("text-anchor", "middle")
|
||||
.style("font-weight", "bold")
|
||||
.text("Countries")
|
||||
|
||||
//var legend = svg.append('g').attr('class', 'legend').attr('transform', 'translate(' + (margin.left/2) + ',0)');
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (window.innerWidth < 450 && window.innerWidth > 400) {
|
||||
return 2.0 * length / margin.bottom;
|
||||
}
|
||||
else if (window.innerWidth < 400) {
|
||||
return 1.0 * length / margin.bottom;
|
||||
}
|
||||
else {
|
||||
return 2.5 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (window.innerWidth < 450 && window.innerWidth > 400) {
|
||||
return 2.0 * length / margin.bottom;
|
||||
}
|
||||
else if (window.innerWidth < 400) {
|
||||
return 1.0 * length / margin.bottom;
|
||||
}
|
||||
else {
|
||||
return 2.5 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("fill", "#cd7f32")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", (5.4) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (window.innerWidth < 450 && window.innerWidth > 400) {
|
||||
return 2.0 * length / margin.bottom;
|
||||
}
|
||||
else if (window.innerWidth < 400) {
|
||||
return 1.0 * length / margin.bottom;
|
||||
}
|
||||
else {
|
||||
return 2.5 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (window.innerWidth < 450 && window.innerWidth > 400) {
|
||||
return 2.0 * length / margin.bottom;
|
||||
}
|
||||
else if (window.innerWidth < 400) {
|
||||
return 1.0 * length / margin.bottom;
|
||||
}
|
||||
else {
|
||||
return 2.5 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("fill", "#bdbdbd")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", (10.0) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (window.innerWidth < 450 && window.innerWidth > 400) {
|
||||
return 2.0 * length / margin.bottom;
|
||||
}
|
||||
else if (window.innerWidth < 400) {
|
||||
return 1.0 * length / margin.bottom;
|
||||
}
|
||||
else {
|
||||
return 2.5 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (window.innerWidth < 450 && window.innerWidth > 400) {
|
||||
return 2.0 * length / margin.bottom;
|
||||
}
|
||||
else if (window.innerWidth < 400) {
|
||||
return 1.0 * length / margin.bottom;
|
||||
}
|
||||
else {
|
||||
return 2.5 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("fill", "#feb24c")
|
||||
|
||||
svg.append("text")
|
||||
.text("Bronze")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5.5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2.5 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return height / margin.bottom + 1.5 * length / margin.bottom
|
||||
}
|
||||
else if (width < 400) {
|
||||
return height / margin.bottom + 0.8 * length / margin.bottom
|
||||
}
|
||||
else {
|
||||
return height / margin.bottom + 2.0 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Silver")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5.5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2.5 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return (5.4) * height / margin.bottom + 1.5 * length / margin.bottom
|
||||
}
|
||||
else if (width < 400) {
|
||||
return (5.4) * height / margin.bottom + 0.8 * length / margin.bottom
|
||||
}
|
||||
else {
|
||||
return (5.4) * height / margin.bottom + 2.0 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Gold")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5.5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2.5 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return (10.0) * height / margin.bottom + 1.5 * length / margin.bottom;
|
||||
}
|
||||
else if (width < 400) {
|
||||
return (10.0) * height / margin.bottom + 0.8 * length / margin.bottom;
|
||||
}
|
||||
else {
|
||||
return (10.0) * height / margin.bottom + 2.0 * length / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width / 19
|
||||
}
|
||||
else {
|
||||
return width / 6
|
||||
}
|
||||
})
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Tokyo 2020 Olympics Performance Summary")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default StackedBarChartMini;
|
||||
372
ReactTool/frontend/src/components/stackedArea-mini.js
Normal file
@@ -0,0 +1,372 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/StackedArea.csv';
|
||||
import img7 from '../components/data/Mini-VLAT/StackedArea.png'
|
||||
|
||||
|
||||
|
||||
class StackedAreaPlotMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://www.theguardian.com/news/datablog/2011/jul/28/top-100-baby-names-oliver-olivia
|
||||
//https://www.theguardian.com/news/datablog/2010/oct/27/baby-names-children-oliver-olivia
|
||||
//https://www.theguardian.com/news/datablog/2012/aug/14/baby-names-2011-harry-amelia-data
|
||||
//https://www.theguardian.com/news/datablog/2013/aug/12/top-100-baby-names-2012-girls-boys-list
|
||||
//https://www.theguardian.com/news/datablog/2014/aug/15/the-top-100-baby-names-in-england-and-wales-2013
|
||||
//https://www.theguardian.com/news/datablog/ng-interactive/2015/aug/17/100-most-popular-baby-names-england-wales-full-list
|
||||
//https://www.d3-graph-gallery.com/stackedarea
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Popular Girls' Names in UK").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
var image = svg.append('image').attr('width', 1.4 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img7).attr('height', 1.1 * height)
|
||||
}
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
const format = d3.timeFormat("%Y");
|
||||
|
||||
d3.csv(data).then(function (data) {
|
||||
data.forEach(function (d) {
|
||||
d.Isla = parseInt(d.Isla);
|
||||
d.Amelia = parseInt(d.Amelia);
|
||||
d.Olivia = parseInt(d.Olivia);
|
||||
//d.Year = format(d.Year);
|
||||
})
|
||||
const keys = data.columns.slice(1)
|
||||
const stackedData = d3.stack()
|
||||
.keys(keys)
|
||||
(data)
|
||||
|
||||
const color = d3.scaleOrdinal()
|
||||
.range(['#3182bd', '#9ecae1', '#deebf7'])
|
||||
|
||||
const x = d3.scaleLinear()
|
||||
.domain(d3.extent(data, function (d) {
|
||||
return d.Year;
|
||||
}))
|
||||
.range([0, width]);
|
||||
|
||||
const y = d3.scaleLinear()
|
||||
.domain([0, 19000])
|
||||
.range([height, 0]);
|
||||
|
||||
function make_x_gridlines() {
|
||||
return d3.axisBottom(x)
|
||||
.ticks(5)
|
||||
}
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y-axis")
|
||||
.call(d3.axisLeft(y))
|
||||
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(x).ticks(5).tickFormat(d3.format("d")))
|
||||
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return -1.4 * margin.left + (margin.top / 1.5) * e.clientWidth / e.clientHeight;
|
||||
}
|
||||
else if (width < 400) {
|
||||
return -1.9 * margin.left + (margin.top / 1.5) * e.clientWidth / e.clientHeight;
|
||||
}
|
||||
else {
|
||||
return - 1.3 * margin.left + (margin.top / 1.5) * e.clientWidth / e.clientHeight;
|
||||
}
|
||||
})
|
||||
.attr("x", 0 - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Number of Girls")
|
||||
.style("font-weight", "bold")
|
||||
.style('font-size', function () {
|
||||
if (width < 500) {
|
||||
return "1.2vh"
|
||||
}
|
||||
})
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("transform", function () {
|
||||
if (width < 500) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.5 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.1 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
})
|
||||
.style("text-anchor", "middle")
|
||||
.style("font-weight", "bold")
|
||||
.text("Year")
|
||||
|
||||
const areaChart = svg.append('g')
|
||||
.attr("clip-path", "url(#clip)")
|
||||
|
||||
const area = d3.area()
|
||||
.x(function (d) {
|
||||
return x(d.data.Year);
|
||||
})
|
||||
.y0(function (d) {
|
||||
return y(d[0]);
|
||||
})
|
||||
.y1(function (d) {
|
||||
return y(d[1]);
|
||||
})
|
||||
|
||||
areaChart
|
||||
.selectAll("mylayers")
|
||||
.data(stackedData)
|
||||
.join("path")
|
||||
.attr("class", function (d) {
|
||||
return "myArea " + d.key
|
||||
})
|
||||
.style("fill", function (d) {
|
||||
return color(d.key);
|
||||
})
|
||||
.attr("d", area)
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(make_x_gridlines()
|
||||
.tickSize(-height)
|
||||
.tickFormat("")
|
||||
)
|
||||
function make_y_gridlines() {
|
||||
return d3.axisLeft(y)
|
||||
.ticks(8)
|
||||
}
|
||||
|
||||
// add the Y gridlines
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_gridlines()
|
||||
.tickSize(-width)
|
||||
.tickFormat("")
|
||||
)
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 500) {
|
||||
return length / 30;
|
||||
}
|
||||
else {
|
||||
return length / 50;
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 500) {
|
||||
return length / 30;
|
||||
}
|
||||
else {
|
||||
return length / 50;
|
||||
}
|
||||
})
|
||||
.attr("fill", "#deebf7")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", (height / margin.bottom) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 500) {
|
||||
return length / 30;
|
||||
}
|
||||
else {
|
||||
return length / 50;
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 500) {
|
||||
return length / 30;
|
||||
}
|
||||
else {
|
||||
return length / 50;
|
||||
}
|
||||
})
|
||||
.attr("fill", "#9ecae1")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", ((height / margin.bottom) / 2.8) * (height / margin.bottom) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 500) {
|
||||
return length / 30;
|
||||
}
|
||||
else {
|
||||
return length / 50;
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 500) {
|
||||
return length / 30;
|
||||
}
|
||||
else {
|
||||
return length / 50;
|
||||
}
|
||||
})
|
||||
.attr("fill", "#3182bd")
|
||||
|
||||
svg.append("text")
|
||||
.text("Olivia")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (2 * width / margin.left) + length / 25;
|
||||
}
|
||||
else {
|
||||
return ((width + (2 * width / margin.left)) + length / 40);
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500) {
|
||||
return height / margin.bottom + length / 45
|
||||
}
|
||||
else {
|
||||
return (0.7 * (height / margin.bottom)) * height / margin.bottom
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Isla")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (2 * width / margin.left) + length / 25;
|
||||
}
|
||||
else {
|
||||
return ((width + (2 * width / margin.left)) + length / 40);
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500) {
|
||||
return (height / margin.bottom) * height / margin.bottom + length / 45;
|
||||
}
|
||||
else {
|
||||
return (1.5) * (height / margin.bottom) * height / margin.bottom
|
||||
}
|
||||
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Amelia")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (2 * width / margin.left) + length / 25;
|
||||
}
|
||||
else {
|
||||
return ((width + (2 * width / margin.left)) + length / 40);
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500) {
|
||||
return ((height / margin.bottom) / 2.8) * (height / margin.bottom) * height / margin.bottom + length / 35
|
||||
}
|
||||
else {
|
||||
return (1.25) * ((height / margin.bottom) / 2.7) * (height / margin.bottom) * height / margin.bottom
|
||||
}
|
||||
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width / 6
|
||||
}
|
||||
else {
|
||||
return width / 3
|
||||
}
|
||||
})
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Popular Girls' names in the UK")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default StackedAreaPlotMini;
|
||||
494
ReactTool/frontend/src/components/stackedbar-mini.js
Normal file
@@ -0,0 +1,494 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/StackedBarGraph.csv';
|
||||
import img2 from '../components/data/Mini-VLAT/StackedBar.png'
|
||||
|
||||
|
||||
|
||||
class StackedBarChart2Mini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//https://www.statista.com/chart/3358/room-service-prices/
|
||||
//https://www.d3-graph-gallery.com/graph/barplot_stacked_basicWide.html
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
//.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("Hotel Costs of Room Service").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img2).attr('height', 1.1 * height)
|
||||
|
||||
}
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
|
||||
|
||||
d3.csv(data).then(function (data) {
|
||||
data.forEach(function (d) {
|
||||
d.Sandwich = parseFloat(d.Sandwich);
|
||||
d.Water = parseFloat(d.Water);
|
||||
d.Peanut = parseFloat(d.Peanut);
|
||||
d.CanOfSoda = parseFloat(d.CanOfSoda);
|
||||
d.Vodka = parseFloat(d.Vodka);
|
||||
d.City = d.City;
|
||||
})
|
||||
console.log(data)
|
||||
|
||||
var subgroups = data.columns.slice(1);
|
||||
|
||||
var groups = data.map(d => (d.City));
|
||||
|
||||
console.log(subgroups)
|
||||
|
||||
var xScale = d3.scaleBand().domain(groups).range([0, width]).padding([0.2])
|
||||
|
||||
if (width < 500) {
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(xScale).tickSizeOuter(0))
|
||||
.selectAll("text")
|
||||
.attr("dy", ".35em")
|
||||
.attr("transform", "rotate(40)")
|
||||
.style("text-anchor", "start")
|
||||
}
|
||||
else {
|
||||
svg.append("g")
|
||||
.attr("class", "x-axis")
|
||||
.attr("transform", `translate(0, ${height})`)
|
||||
.call(d3.axisBottom(xScale).tickSizeOuter(0))
|
||||
.selectAll("text")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var yScale = d3.scaleLinear().domain([0, 70]).range([height, 0]);
|
||||
svg.append("g").attr("class", "y-axis").call(d3.axisLeft(yScale)).selectAll("text")
|
||||
.style("font-size", function () {
|
||||
if (length < 700) {
|
||||
return 1.4 * (length / margin.top)
|
||||
}
|
||||
})
|
||||
|
||||
const color = d3.scaleOrdinal()
|
||||
.domain(subgroups)
|
||||
.range(['#7fc97f', '#beaed4', '#fdc086', '#fb9a99', '#386cb0'])
|
||||
|
||||
//stack the data? --> stack per subgroup
|
||||
const stackedData = d3.stack()
|
||||
.keys(subgroups)
|
||||
(data)
|
||||
|
||||
// gridlines in y axis function
|
||||
function make_y_gridlines() {
|
||||
return d3.axisLeft(yScale)
|
||||
.ticks(11)
|
||||
}
|
||||
|
||||
// add the Y gridlines
|
||||
svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.call(make_y_gridlines()
|
||||
.tickSize(-width)
|
||||
.tickFormat("")
|
||||
)
|
||||
//This is for Stacked Bar Graph
|
||||
// Show the bars
|
||||
svg.append("g")
|
||||
.selectAll("g")
|
||||
// Enter in the stack data = loop key per key = group per group
|
||||
.data(stackedData)
|
||||
.enter().append("g")
|
||||
.attr("fill", function (d) { return color(d.key); })
|
||||
.selectAll("rect")
|
||||
// enter a second time = loop subgroup per subgroup to add all rectangles
|
||||
.data(function (d) { return d; })
|
||||
.enter().append("rect")
|
||||
.attr("x", function (d) { return xScale(d.data.City); })
|
||||
.attr("y", function (d) { return yScale(d[1]); })
|
||||
.attr("height", function (d) { return yScale(d[0]) - yScale(d[1]); })
|
||||
.attr("width", xScale.bandwidth())
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "y-label")
|
||||
.attr("transform", "rotate(-90)")
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return - margin.left + (margin.top / 5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else if (width < 400) {
|
||||
return - margin.left + (margin.top / 19.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
else {
|
||||
return - margin.left + (margin.top / 2.5) * e.clientWidth / e.clientHeight
|
||||
}
|
||||
})
|
||||
.attr("x", - (height / 1.9))
|
||||
.attr("dy", "1em")
|
||||
.style("text-anchor", "middle")
|
||||
.text("Cost ($)")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
svg.append("text")
|
||||
.attr("class", "x-label")
|
||||
.attr("transform", function () {
|
||||
if (window.innerWidth < 500) {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.6 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
else {
|
||||
return "translate(" + (width / 1.9) + " ," + (height + 1.1 * margin.top - (margin.top / 1.5)) + ")"
|
||||
}
|
||||
})
|
||||
.style("text-anchor", "middle")
|
||||
.style("font-weight", "bold")
|
||||
.text("Cities")
|
||||
|
||||
var dataNormalized = []
|
||||
data.forEach(function (d) {
|
||||
// Compute the total
|
||||
var tot = 0
|
||||
for (var i in subgroups) { const name = subgroups[i]; tot += +d[name] }
|
||||
// Now normalize
|
||||
for (var i in subgroups) { const name = subgroups[i]; d[name] = d[name] / tot * 100 }
|
||||
})
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (0.6 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("fill", "#386cb0")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (0.6 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", (height / margin.bottom) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("fill", "#fb9a99")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (0.6 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", ((height / margin.bottom) / 2.7) * (height / margin.bottom) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("fill", "#fdc086")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (0.6 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", ((height / margin.bottom) / 1.85) * (height / margin.bottom) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("fill", "#beaed4")
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", function () {
|
||||
if (width < 400) {
|
||||
return width + (0.6 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", ((height / margin.bottom) / 1.4) * (height / margin.bottom) * height / margin.bottom)
|
||||
.attr("width", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("height", function () {
|
||||
if (width < 400) {
|
||||
return 0.9 * length / margin.left
|
||||
}
|
||||
else {
|
||||
return 1.7 * length / margin.left
|
||||
}
|
||||
})
|
||||
.attr("fill", "#7fc97f")
|
||||
|
||||
svg.append("text")
|
||||
.text("Vodka")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return height / margin.bottom + (1.3 * length / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return height / margin.bottom + (0.7 * length / margin.left)
|
||||
}
|
||||
else {
|
||||
return height / margin.bottom + (1.7 * length / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Soda")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return ((height / margin.bottom) * height / margin.bottom + (1.3 * length / margin.left));
|
||||
}
|
||||
else if (width < 400) {
|
||||
return ((height / margin.bottom) * height / margin.bottom + (0.7 * length / margin.left));
|
||||
}
|
||||
else {
|
||||
return ((height / margin.bottom) * height / margin.bottom + (1.7 * length / margin.left));
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Peanut")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return ((height / margin.bottom) / 2.7) * (height / margin.bottom) * height / margin.bottom + (1.3 * length / margin.left);
|
||||
}
|
||||
else if (width < 400) {
|
||||
return ((height / margin.bottom) / 2.7) * (height / margin.bottom) * height / margin.bottom + (0.7 * length / margin.left);
|
||||
}
|
||||
else {
|
||||
return ((height / margin.bottom) / 2.7) * (height / margin.bottom) * height / margin.bottom + (1.7 * length / margin.left);
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Water")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return ((height / margin.bottom) / 1.85) * (height / margin.bottom) * height / margin.bottom + (1.3 * length / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return ((height / margin.bottom) / 1.85) * (height / margin.bottom) * height / margin.bottom + (0.7 * length / margin.left)
|
||||
}
|
||||
else {
|
||||
return ((height / margin.bottom) / 1.85) * (height / margin.bottom) * height / margin.bottom + (1.7 * length / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg.append("text")
|
||||
.text("Sandwich")
|
||||
.attr("x", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return width + (5 * width / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return width + (2 * width / margin.left)
|
||||
}
|
||||
else {
|
||||
return width + (6 * width / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("y", function () {
|
||||
if (width < 500 && width > 400) {
|
||||
return ((height / margin.bottom) / 1.4) * (height / margin.bottom) * height / margin.bottom + (1.3 * length / margin.left)
|
||||
}
|
||||
else if (width < 400) {
|
||||
return ((height / margin.bottom) / 1.4) * (height / margin.bottom) * height / margin.bottom + (0.7 * length / margin.left)
|
||||
}
|
||||
else {
|
||||
return ((height / margin.bottom) / 1.4) * (height / margin.bottom) * height / margin.bottom + (1.7 * length / margin.left)
|
||||
}
|
||||
})
|
||||
.attr("class", "legend-value")
|
||||
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", width / 3)
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("Room Service Prices")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default StackedBarChart2Mini;
|
||||
222
ReactTool/frontend/src/components/treeMap-mini.js
Normal file
@@ -0,0 +1,222 @@
|
||||
import React, { Component } from 'react';
|
||||
import * as d3 from 'd3'
|
||||
import * as topojson from 'topojson';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import data from './data/Treemap.json';
|
||||
import img4 from '../components/data/Mini-VLAT/TreeMap.png'
|
||||
|
||||
|
||||
|
||||
class TreeMapMini extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.drawChart()
|
||||
}
|
||||
divResize(e) {
|
||||
console.log('div was resized', e)
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.drawChart()
|
||||
}
|
||||
|
||||
drawChart() {
|
||||
//Data Source: Nielsen Top 100 January 2010 Unique Visitors
|
||||
//https://www.d3-graph-gallery.com/treemap.html
|
||||
var e = document.getElementById("graph_box");
|
||||
const length = Math.min(e.clientHeight, e.clientWidth)
|
||||
|
||||
if (length < 570) {
|
||||
const margin = { top: length / 7, right: length / 9, bottom: length / 7, left: length / 9 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
//svg.append("text").attr("class", 'bubbleTitle').text("The Number of Unique Visitors for Websites in 2010").style("font-weight", 'bolder').attr('x', 1.2 * margin.top).attr('y', 1.2 * margin.top).style('font-size', 0.04 * height)
|
||||
|
||||
var image = svg.append('image').attr('width', 1.2 * width).attr('x', 0).attr('y', margin.top * height / width).attr('xlink:href', img4).attr('height', 1.1 * height)
|
||||
}
|
||||
else {
|
||||
const margin = { top: length / 7, right: length / 7, bottom: length / 7, left: length / 7 },
|
||||
width = length - margin.left - margin.right,
|
||||
height = length - margin.top - margin.bottom;
|
||||
|
||||
|
||||
// append the svg object to the body of the page
|
||||
d3.select("#graph_box").select("svg").remove();
|
||||
const svg = d3.select("#graph_box")
|
||||
.append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", `translate(${margin.left},${margin.top})`);
|
||||
|
||||
svg.append("rect").attr("width", "100%").attr("height", "100%").attr("fill", "black")
|
||||
|
||||
|
||||
// Give the data to this cluster layout:
|
||||
const root = d3.hierarchy(data).sum(function (d) {
|
||||
return d.value
|
||||
}) // Here the size of each leave is given in the 'value' field in input data
|
||||
|
||||
|
||||
// Then d3.treemap computes the position of each element of the hierarchy
|
||||
d3.treemap()
|
||||
.size([width, height])
|
||||
.paddingTop(25)
|
||||
.paddingRight(7)
|
||||
.paddingInner(3) // Padding between each rectangle
|
||||
//.paddingOuter(1)
|
||||
//.padding(20)
|
||||
(root)
|
||||
|
||||
// prepare a color scale
|
||||
const color = d3.scaleOrdinal()
|
||||
.domain(["boss1", "boss2", "boss3", "boss4", "boss5"])
|
||||
.range(['#7fc97f', '#beaed4', '#fdc086', '#fb9a99', '#386cb0'])
|
||||
|
||||
// And a opacity scale
|
||||
const opacity = d3.scaleLinear()
|
||||
.domain([10, 30])
|
||||
.range([.5, 1])
|
||||
|
||||
// use this information to add rectangles:
|
||||
|
||||
|
||||
svg
|
||||
.selectAll("rect")
|
||||
.data(root.leaves())
|
||||
.join("rect")
|
||||
.attr("class", "tree-rect")
|
||||
.attr('x', function (d) {
|
||||
return d.x0;
|
||||
})
|
||||
.attr('y', function (d) {
|
||||
return d.y0;
|
||||
})
|
||||
.attr('width', function (d) {
|
||||
return d.x1 - d.x0;
|
||||
})
|
||||
.attr('height', function (d) {
|
||||
return d.y1 - d.y0;
|
||||
})
|
||||
.style("stroke", "black")
|
||||
.style("fill", function (d) {
|
||||
return color(d.parent.data.name)
|
||||
})
|
||||
.style("opacity", function (d) {
|
||||
return 0.7
|
||||
})
|
||||
|
||||
// and to add the text labels
|
||||
svg
|
||||
.selectAll("text")
|
||||
.data(root.leaves())
|
||||
.enter()
|
||||
.append("text")
|
||||
//.attr("class", "tree-text")
|
||||
.attr("transform", function (d) {
|
||||
if (d.data.name === "LinkedIn" || d.data.name === "MSN/WindowsLive/Bing") {
|
||||
return "translate(" + (d.x0 + 5) + "," + (d.y0 + 20) + ")" + " " + "rotate(90)";
|
||||
}
|
||||
else if (d.data.name === "Wal-Mart" || d.data.name === "Craigslist" || d.data.name === 'Target') {
|
||||
return "translate(" + (d.x0 + 4) + "," + (d.y0 + 15) + ")" + " " + "rotate(45)";
|
||||
}
|
||||
else {
|
||||
return "translate(" + (d.x0 + 5) + "," + (d.y0 + 20) + ")" + " " + "rotate(0)";
|
||||
}
|
||||
|
||||
}) // +20 to adjust position (lower)
|
||||
.text(function (d) {
|
||||
return d.data.name.replace('mister_', '')
|
||||
})
|
||||
.attr("class", "treemap-label")
|
||||
.attr("x", function (d) {
|
||||
if (length < 600) {
|
||||
if (d.data.name == "LinkedIn" || d.data.name == 'MSN/WindowsLive/Bing') {
|
||||
return -16 * length / length
|
||||
}
|
||||
else {
|
||||
return -3 * length / length
|
||||
}
|
||||
}
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
if (length < 650) {
|
||||
if (d.data.name == "LinkedIn") {
|
||||
return "0"
|
||||
}
|
||||
else if (d.data.name == "Conduit") {
|
||||
return -0.5 * (d.y1 - d.y0);
|
||||
}
|
||||
else {
|
||||
return -length / margin.top
|
||||
}
|
||||
}
|
||||
})
|
||||
.style('font-size', function (d) {
|
||||
if (width < 500) {
|
||||
return 1.1 * (length / margin.top)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// Add title for the 3 groups
|
||||
svg
|
||||
.selectAll("titles")
|
||||
.data(root.descendants().filter(function (d) {
|
||||
return d.depth == 1
|
||||
}))
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr("x", function (d) {
|
||||
return d.x0
|
||||
})
|
||||
.attr("y", function (d) {
|
||||
return d.y0 + 21
|
||||
})
|
||||
.text(function (d) {
|
||||
return d.data.name
|
||||
})
|
||||
//.attr("class", "tree-labels")
|
||||
.style("font-weight", "bold")
|
||||
.attr("class", "x-label")
|
||||
|
||||
// Add title for the 3 groups
|
||||
svg
|
||||
.append("text")
|
||||
.attr("class", "title")
|
||||
.attr("x", width / margin.left)
|
||||
.attr("y", -length / margin.top) // +20 to adjust position (lower)
|
||||
.text("The Number of Unique Visitors for Websites")
|
||||
.attr("fill", "black")
|
||||
.style("font-weight", "bold")
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
|
||||
return (
|
||||
<div id={'graph_box'}>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default TreeMapMini;
|
||||
13
ReactTool/frontend/src/index.css
Normal file
@@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
18
ReactTool/frontend/src/index.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
1
ReactTool/frontend/src/logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
111
ReactTool/frontend/src/pages/introduction.js
Normal file
@@ -0,0 +1,111 @@
|
||||
import React, { Component, useState, useEffect } from 'react';
|
||||
import { Col, Row, Navbar, Button } from 'react-bootstrap';
|
||||
import { PDFViewer } from '@react-pdf/renderer';
|
||||
import { Document, Page } from 'react-pdf';
|
||||
|
||||
class Intro extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
go_to_tutorial() {
|
||||
var pageType = {
|
||||
pathname: '/tutorial',
|
||||
state: {
|
||||
data: {
|
||||
}
|
||||
}
|
||||
}
|
||||
this.props.history.push(pageType)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
var user = navigator.userAgent
|
||||
var browser_supported = true //user.includes('Chrome')
|
||||
|
||||
console.log(user)
|
||||
var mobile_device = /Opera Mini/i.test(navigator.userAgent)
|
||||
if (mobile_device || !browser_supported) {
|
||||
return (<>
|
||||
<Row className={'justify-content-center'}>
|
||||
<Col lg={6} className={'text-box text-justify'}>
|
||||
|
||||
<p>Sorry, your browser is not supported.</p>
|
||||
<p>Please download <a href={'https://www.mozilla.org/en-US/firefox/new/'}>Firefox</a> (version 80 or newer) or <a href={'https://www.google.com/chrome/'}>Chrome</a> (version 85 or newer) on your computer and try again.</p>
|
||||
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row className={'justify-content-center no-margin-row'}>
|
||||
<div className='heading-term'>Consent Form</div>
|
||||
<div className={'terms-container'}>
|
||||
<div className='terms'>
|
||||
<p>We invite you to participate in a research study being conducted by investigators from Washington University in St. Louis. You are being asked to participate in this research study because you are an English-speaking adult in the United States. The purpose of the study is to develop an instrument that measures how well people can read, understand, and use data visualizations to solve problems.</p>
|
||||
<p>If you agree to participate, we would like you to questions about a series of data visualization. For each question, you will see a data visualization and a problem to solve. Choose the BEST answer to the questions. If you are unsure, Select ''Skip'' instead of guessing. You are also free to skip any questions that you prefer not to answer. In the end, you will complete a brief demographic survey.</p>
|
||||
<p>We would like to use the data we are obtaining in this study for studies going on right now as well as studies that are conducted in the future.</p>
|
||||
<p>These studies may provide additional information that will be helpful in developing better visual communication tools. It is unlikely that what we learn from these studies will have a direct benefit to you. There are no plans to provide financial compensation to you should this occur. By allowing us to use your data you give up any property rights you may have in the data.</p>
|
||||
<p>We will share your data with other researchers. They may be doing research in areas similar to this research or in other unrelated areas. These researchers may be at Washington University, at other research centers and institutions, or industry sponsors of research. We may also share your research data with large data repositories (a repository is a database of information) for broad sharing with the research community. If your individual research data is placed in one of these repositories only qualified researchers, who have received prior approval from individuals that monitor the use of the data, will be able to look at your information.</p>
|
||||
<p>Your data will be stored without your name or any other kind of link that would enable us to identify which data are yours. Therefore, it will be available indefinitely for use in future research studies without your additional consent and cannot be removed.</p>
|
||||
{/* <p>Approximately 5100 people will take part in this study at Washington University.</p> */}
|
||||
<p>There are no known risks from being in this study.</p>
|
||||
<p>You will not benefit personally. However, we hope that others may benefit in the future from what we learn as a result of this study. You will not have any costs for being in this research study.</p>
|
||||
<p>You will be paid for being in this research study. You will receive a pay of $8 for completing this quiz. At the end of the study, copy your survey code back to Prolific to receive your payment.</p>
|
||||
<p>We will keep the information you provide confidentially. This survey is completely anonymous; we will not collect any personally identifiable information. We will only have access to your Prolific ID only, which we will use solely for payment purposes. </p>
|
||||
<p>Any report or article that we write will not include information that can directly identify you. The journals that publish these reports or articles require that we share the information that was collected for this study with others to make sure the results of this study are correct and help develop new ideas for research. Your information will be shared in a way that cannot directly identify you.</p>
|
||||
<p>Federal regulatory agencies and Washington University, including the Washington University Institutional Review Board (a committee that reviews and approves research studies) and the Human Research Protection Office, may inspect and copy records pertaining to this research.
|
||||
|
||||
Your participation in this study is completely voluntary. You may choose not to take part at all. If you decide to participate in the study, you may stop participating at any time. Any data that was collected as part of this study will remain as part of the study records and cannot be removed. If you decide not to take part in the study or if you stop participating at any time, you won’t be penalized or lose any benefits for which you otherwise qualify.
|
||||
</p>
|
||||
<p>If you do not wish to participate in this study or want to end your participation in the study, close the browser tab without answering any of the questions.</p>
|
||||
|
||||
<p> We encourage you to ask questions. If you have any questions about the research study itself, please contact Saugat Pandey (p.saugat@wustl.edu). If you feel you have been harmed from being in the study, please contact Alvitta Ottley (alvitta@wustl.edu). If you have questions, concerns, or complaints about your rights as a research participant, please contact the Human Research Protection Office at 1-(800)-438-0445 or email hrpo@wustl.edu. General information about being a research participant can be found on the Human Research Protection Office website, http://hrpo.wustl.edu. To offer input about your experiences as a research participant or to speak to someone other than the research staff, call the Human Research Protection Office at the number above.</p>
|
||||
|
||||
<p>Thank you very much for your consideration of this research study.</p>
|
||||
</div>
|
||||
{/* <p>Taking part in this research study is completely voluntary. You may choose not to take part at all.
|
||||
If you decide to be in this study, you may stop participating at any time. Any data that was collected
|
||||
as part of your participation in the study will remain as part of the study records and cannot be removed.
|
||||
As a part of this study:
|
||||
<ul>
|
||||
<li><b>We will not collect your name or any identifying information about you. It will not be possible
|
||||
to link you to your responses on the survey.</b></li>
|
||||
|
||||
<li>We will store you response to every question along with the time taken to solve every question and total score.</li>
|
||||
|
||||
|
||||
{/* <li>We will store information about your mouse interaction (e.g. what you clicked) when answering the survey questions.</li>
|
||||
|
||||
<li>We may allow other researchers to use the interaction data that we collect.
|
||||
Researchers from other universities can request to use the data.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
We encourage you to ask questions. If you have any questions about the research study itself, please contact: Alvitta Ottley (alvitta@wustl.edu). If you have questions, concerns, or complaints about your rights as a research participant, please contact the Human Research Protection Office at 660 South Euclid Avenue, Campus Box 8089, St. Louis, MO 63110, 1-(800)-438-0445 or email hrpo@wusm.wustl.edu. General information about being a research participant can be found on the Human Research Protection Office web site, http://hrpo.wustl.edu/. To offer input about your experiences as a research participant or to speak to someone other than the research staff, call the Human Research Protection Office at the number above.
|
||||
Thank you very much for your consideration of this research study.
|
||||
</p> */}
|
||||
|
||||
<div className={'text-center'}><Button onClick={this.go_to_tutorial.bind(this)} className={'btn-sm'} variant={"success"}>
|
||||
I agree to participate.
|
||||
</Button></div>
|
||||
</div>
|
||||
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Intro;
|
||||
65
ReactTool/frontend/src/pages/thank_you.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Col, Row, Button, InputGroup, FormControl} from 'react-bootstrap';
|
||||
import {CopyToClipboard} from 'react-copy-to-clipboard';
|
||||
|
||||
class ThankYou extends Component {
|
||||
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.location.state != null) {
|
||||
this.setState({
|
||||
value: this.props.location.state !== undefined ? this.props.location.state.data.session_id : "Invalid value",
|
||||
copied: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('attempting to render')
|
||||
|
||||
if (this.props.location.state == null) {
|
||||
return (<p>Unknown session. Please start from the <a href={'#/'}> consent page</a></p>)
|
||||
}
|
||||
|
||||
if (this.state == null) {
|
||||
return (<p>Loading...</p>)
|
||||
}
|
||||
|
||||
return (
|
||||
<Row className={'justify-content-center no-margin-row'}>
|
||||
<Col lg={6} className={'text-box text-justify'}>
|
||||
<p>Thank you for participating in our study. You responses have been recorded.</p>
|
||||
|
||||
|
||||
{/*
|
||||
<InputGroup size='lg' className="mb-3">
|
||||
<FormControl
|
||||
placeholder="session_id"
|
||||
aria-label="session_id"
|
||||
aria-describedby="Session Code"
|
||||
value={this.state.value}
|
||||
|
||||
/>
|
||||
|
||||
<CopyToClipboard text={this.state.value}
|
||||
onCopy={() => this.setState({copied: true})}>
|
||||
<Button
|
||||
variant="outline-secondary">{this.state.copied ? <>Copied!</> : <>Copy</>}</Button>
|
||||
</CopyToClipboard>
|
||||
|
||||
</InputGroup> */}
|
||||
|
||||
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ThankYou;
|
||||
93
ReactTool/frontend/src/pages/tutorial.js
Normal file
@@ -0,0 +1,93 @@
|
||||
import React, { Component, useState, useEffect } from 'react';
|
||||
import { Col, Row, Navbar, Button, Image, ButtonGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
|
||||
// uncomment if running on local backend
|
||||
const backend_path_prefix = '.'
|
||||
|
||||
class Tutorial extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
onUnload(e) {
|
||||
|
||||
}
|
||||
|
||||
on_experiment_click(e) {
|
||||
var pageType = {
|
||||
pathname: '/experiment',
|
||||
state: {
|
||||
data: {
|
||||
'session_id': this.state.session_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(pageType)
|
||||
this.props.history.push(pageType)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
fetch('./new_session_id', {
|
||||
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
start_time: 'TODO'
|
||||
})
|
||||
})
|
||||
.then(res => res.json()).then(data => {
|
||||
console.log(data.new_id)
|
||||
this.setState({
|
||||
session_id: data.new_id
|
||||
})
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
//window.removeEventListener("beforeunload", this.onUnload);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (this.props.location.state == null) {
|
||||
return (<p>Unknown session. Please start from the <a href={'#/'}> consent page</a></p>)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row className={'justify-content-center tutorial-body'}>
|
||||
<Col lg={6} className={'text-box text-justify'}>
|
||||
|
||||
<p className='head_1'>Intructions</p>
|
||||
<ul>
|
||||
<li className='int_1'>You will be given 12 multiple-choice questions</li>
|
||||
<li className='int_1'>Answer to the best of your ability. If you are unsure,you may skip the questions instead of guessing.</li>
|
||||
{/* <li className='int_1'>Please do not take this test if you are color blind. Here is a link to a separate test: <a href='https://colormax.org/color-blind-test/' target="_blank">https://colormax.org/color-blind-test/</a></li> */}
|
||||
{/* <li>We will store information about your mouse interaction (e.g. what you clicked) when answering the survey questions.</li> */}
|
||||
|
||||
</ul>
|
||||
<p className='head_2'><b>Important: You will have 25 seconds to answer each question.</b> Answer to the best of your ability. You may <b>skip the questions instead of guessing</b> if you are unsure.</p>
|
||||
|
||||
<div className={'text-center'}>
|
||||
<Button onClick={this.on_experiment_click.bind(this)}
|
||||
className={'btn-sm'} variant={"success"}>
|
||||
Start the experiment.
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
<p className={'text-box'}></p>
|
||||
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Tutorial;
|
||||
379
ReactTool/frontend/src/pages/visualization_quiz.js
Normal file
@@ -0,0 +1,379 @@
|
||||
import React, { Component, useLayoutEffect, useState, useEffect, FunctionComponent } from 'react';
|
||||
import { Container, Col, Row, Navbar, Button, ButtonGroup, ToggleButton, Form, InputGroup } from 'react-bootstrap';
|
||||
import '../App.css';
|
||||
import ProgressBar from "@ramonak/react-progress-bar";
|
||||
import Countdown from 'react-countdown';
|
||||
|
||||
import AreaChartMini from "../components/areaChart-mini";
|
||||
import BarChartMini from "../components/barChart-mini";
|
||||
import BubbleChartMini from "../components/bubbleChart-mini";
|
||||
import ChoroplethMini from "../components/choropleth-mini";
|
||||
import HistogramMini from "../components/histogram-mini";
|
||||
import LineChartMini from "../components/linechart-mini";
|
||||
import PieChartMini from "../components/pieChart-mini";
|
||||
import ScatterPlotMini from "../components/scatterplot-mini";
|
||||
import StackedBarChartMini from "../components/stacked100bar-mini";
|
||||
import StackedAreaPlotMini from "../components/stackedArea-mini";
|
||||
import StackedBarChart2Mini from "../components/stackedbar-mini";
|
||||
import TreeMapMini from "../components/treeMap-mini";
|
||||
|
||||
import img1 from '../components/data/VLAT-Pics/Scatterplot.png'
|
||||
import img2 from '../components/data/VLAT-Pics/StackedBar.png'
|
||||
import img3 from '../components/data/VLAT-Pics/BubbleChart.png'
|
||||
import img4 from '../components/data/VLAT-Pics/TreeMap.png'
|
||||
import img5 from '../components/data/VLAT-Pics/StackedBar100.png'
|
||||
import img6 from '../components/data/VLAT-Pics/Histogram.png'
|
||||
import img7 from '../components/data/VLAT-Pics/StackedArea.png'
|
||||
import img8 from '../components/data/VLAT-Pics/Choropleth.png'
|
||||
import img9 from '../components/data/VLAT-Pics/BarGraph.png'
|
||||
import img10 from '../components/data/VLAT-Pics/AreaChart.png'
|
||||
import img11 from '../components/data/VLAT-Pics/Pie.png'
|
||||
import img12 from '../components/data/VLAT-Pics/LineChart.png'
|
||||
|
||||
|
||||
|
||||
let minivis = [
|
||||
{ 'vis': BarChartMini, 'type': 'BarChart', 'question': 'What is the average internet speed in Japan?', 'options': ["42.30 Mbps", "40.51 Mbps", "35.25 Mbps", "16.16 Mbps", "Skip"], 'correct_answer': 1, 'cimage': img9 },
|
||||
{ 'vis': AreaChartMini, 'type': 'AreaChart', 'question': 'What was the average price of pount of coffee beans in October 2019?', 'options': ["$0.71", "$0.90", "$0.80", "$0.63", "Skip"], 'correct_answer': 0, 'cimage': img10 },
|
||||
{ 'vis': BubbleChartMini, 'type': 'BubbleChart', 'question': 'Which city\'s metro system has the largest number of stations?', 'options': ['Beijing', 'Shanghai', 'London', 'Seoul', "Skip"], 'correct_answer': 1, 'cimage': img3 },
|
||||
{ 'vis': ChoroplethMini, 'type': 'Choropleth', 'question': 'In 2020, the unemployment rate for Washington (WA) was higher than that of Wisconsin (WI).', 'options': ['True', 'False', "Skip"], 'correct_answer': 0, 'cimage': img8 },
|
||||
{ 'vis': HistogramMini, 'type': 'Histogram', 'question': 'What distance have customers traveled in the taxi the most?', 'options': ["60 - 70 Km", "30 - 40 Km", "20 - 30 Km", "50 - 60 Km", "Skip"], 'correct_answer': 1, 'cimage': img6 },
|
||||
{ 'vis': LineChartMini, 'type': 'LineChart', 'question': 'What was the price of a barrel of oil in February 2020?', 'options': ["$50.54", "$47.02", "$42.34", "$42.34", "Skip"], 'correct_answer': 0, 'cimage': img12 },
|
||||
{ 'vis': TreeMapMini, 'type': 'TreeMap', 'question': 'eBay is nested in the Software category.', 'options': ['True', 'False', 'Skip'], 'correct_answer': 1, 'cimage': img4 },
|
||||
{ 'vis': ScatterPlotMini, 'type': 'ScatterPlot', 'question': 'There is a negative linear relationship between the height and the weight of the 85 males.', 'options': ['True', 'False', 'Skip'], 'correct_answer': 1, 'cimage': img1 },
|
||||
{ 'vis': StackedBarChartMini, 'type': 'StackedBarChart', 'question': 'Which country has the lowest proportion of Gold medals?', 'options': ["Great Britain", "U.S.A.", "Japan", "Australia", 'Skip'], 'correct_answer': 0, 'cimage': img5 },
|
||||
{ 'vis': StackedAreaPlotMini, 'type': 'StackedAreaPlot', 'question': 'What was the ratio of girls named \'Isla\' to girls named \'Amelia\' in 2012 in the UK?', 'options': ["1 to 1", "1 to 2", "1 to 3", "1 to 4", "Skip"], 'correct_answer': 1, 'cimage': img7 },
|
||||
{ 'vis': StackedBarChart2Mini, 'type': 'StackedBarChart2', 'question': 'What is the cost of peanuts in Seoul?', 'options': ["$6.1", "$5.2", "$7.5", "$4.5", "Skip"], 'correct_answer': 0, 'cimage': img2 },
|
||||
{ 'vis': PieChartMini, 'type': 'PieChart', 'question': 'What is the approximate global smartphone market share of Samsung?', 'options': ["17.6%", "25.3%", "10.9%", "35.2%", 'Skip'], 'correct_answer': 0, 'cimage': img11 }
|
||||
];
|
||||
|
||||
|
||||
|
||||
var score_1 = 0
|
||||
var score_2 = 0
|
||||
let initTime = 0
|
||||
let endTime = 0
|
||||
var num = 12
|
||||
//var correct_collec = []
|
||||
//var wrong_collec = []
|
||||
var correct_collect = []
|
||||
var wrong_collect = []
|
||||
var random_list = [0, 1]
|
||||
|
||||
class VisQuiz extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
session_id: this.props.location.state.data.session_id,
|
||||
current_visualization_index: 0,
|
||||
score: 0,
|
||||
current_mini_index: 0,
|
||||
list_of_min_vis: this.shuffle(minivis),
|
||||
responses: {},
|
||||
mini_responses: {},
|
||||
resize_bool: true,
|
||||
device_info: '',
|
||||
form_incomplete: false,
|
||||
demographic_questions: {
|
||||
'sex': null,
|
||||
'age': null,
|
||||
'education': null,
|
||||
'familiarity': null
|
||||
},
|
||||
demographics_incomplete: true,
|
||||
comment: '',
|
||||
width: 0,
|
||||
height: 0,
|
||||
mini_score: 0,
|
||||
}
|
||||
)
|
||||
|
||||
window.addEventListener('resize', this.handleWindowResize.bind(this))
|
||||
}
|
||||
|
||||
handleWindowResize(e) {
|
||||
this.setState({
|
||||
resize_bool: !this.state.resize_bool
|
||||
})
|
||||
}
|
||||
handleTextChange(e) {
|
||||
this.setState({ comment: e.target.value })
|
||||
}
|
||||
|
||||
handleDemographicChange(e) {
|
||||
console.log(this.state)
|
||||
var new_dq = this.state.demographic_questions
|
||||
new_dq[e.target.id] = e.target.value
|
||||
|
||||
var incomplete = false
|
||||
for (var key in new_dq) {
|
||||
if (new_dq[key] == null) {
|
||||
incomplete = true
|
||||
}
|
||||
}
|
||||
if (e.value == 'oth') {
|
||||
alert('Hello')
|
||||
}
|
||||
|
||||
this.setState({ demographic_questions: new_dq, demographics_incomplete: incomplete })
|
||||
}
|
||||
|
||||
clicked_mini_answer(type, question, response, truth, time) {
|
||||
if (response === minivis[this.state.current_mini_index]['options'][truth]) {
|
||||
this.state.mini_score = this.state.mini_score + 1
|
||||
}
|
||||
this.setState({
|
||||
current_mini_index: this.state.current_mini_index + 1,
|
||||
})
|
||||
endTime = Math.abs((Date.now() - initTime) / 1000)
|
||||
this.state.mini_responses[question] = { response: response, truth: truth, time: endTime }
|
||||
this.setState({
|
||||
device_info: navigator.userAgent
|
||||
})
|
||||
score_2 = this.state.mini_score
|
||||
}
|
||||
|
||||
|
||||
|
||||
shuffle(array) {
|
||||
//https://bost.ocks.org/mike/shuffle/
|
||||
var m = array.length, t, i;
|
||||
|
||||
// While there remain elements to shuffle…
|
||||
while (m) {
|
||||
|
||||
// Pick a remaining element…
|
||||
i = Math.floor(Math.random() * m--);
|
||||
|
||||
// And swap it with the current element.
|
||||
t = array[m];
|
||||
array[m] = array[i];
|
||||
array[i] = t;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
|
||||
on_survey_click() {
|
||||
|
||||
fetch('./record_responses_to_db', {
|
||||
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
session_id: this.state.session_id,
|
||||
responses: this.state.responses,
|
||||
mini_responses: this.state.mini_responses,
|
||||
score: this.state.score,
|
||||
mini_score: this.state.mini_score,
|
||||
device: this.state.device_info,
|
||||
demographic_responses: this.state.demographic_questions,
|
||||
comment: this.state.comment,
|
||||
height: window.innerHeight,
|
||||
width: window.innerWidth
|
||||
})
|
||||
})
|
||||
.then(res => res.json()).then(data => {
|
||||
//var message = 'Warning!\n\nNavigating away from this page will delete your text if you haven\'t already saved it.';
|
||||
//e.returnValue = message;
|
||||
//return message;
|
||||
})
|
||||
|
||||
var pageType = {
|
||||
pathname: '/score',
|
||||
state: {
|
||||
data: {
|
||||
'session_id': this.state.session_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
this.props.history.push(pageType)
|
||||
}
|
||||
timeout() {
|
||||
alert("Time is up! Please select 'Ok' to proceed to the next question.")
|
||||
this.setState({
|
||||
current_visualization_index: this.state.current_visualization_index + 1,
|
||||
})
|
||||
}
|
||||
getRandom() {
|
||||
return Math.random();
|
||||
}
|
||||
minitimeout() {
|
||||
alert("Time is up! Please select 'Ok' to proceed to the next question.")
|
||||
this.setState({
|
||||
current_mini_index: this.state.current_mini_index + 1,
|
||||
})
|
||||
}
|
||||
randomChoose() {
|
||||
return random_list[Math.floor(Math.random() * random_list.length)]
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
//console.log("Random number is ", this.randomChoose())
|
||||
//const { refCallback, time } = this.props;
|
||||
console.log("Random array is ", this.randomChoose())
|
||||
const hoursMinSecs = { hours: 0, minutes: 0, seconds: 10 }
|
||||
initTime = Date.now()
|
||||
console.log("Starting Time is : " + initTime)
|
||||
console.log('render')
|
||||
|
||||
if (this.props.location.state == undefined) {
|
||||
window.location.href = "/";
|
||||
return (<p>Unknown session. Please start from the <a href={'/'}> consent page</a></p>)
|
||||
}
|
||||
let ages = []
|
||||
for (var i = 18; i < 100; i++) {
|
||||
ages.push(i)
|
||||
}
|
||||
|
||||
if (this.state == null) {
|
||||
return (<p>Loading...</p>)
|
||||
}
|
||||
if (this.state.current_mini_index < this.state.list_of_min_vis.length) {
|
||||
const options = minivis[this.state.current_mini_index]['options'].map((item, i) =>
|
||||
// <Button variant="secondary" size="sm" className={'question-option'} id={`button_option_${i}`} key={`button_option_${i}`} onClick={() =>
|
||||
// /this.clicked_answer(minivis[this.state.current_mini_index]['type'], minivis[this.state.current_mini_index]['question'], item, minivis[this.state.current_mini_index]['correct_answer'], "timeTaken", minivis[this.state.current_mini_index]['cimage'])}>
|
||||
// {item}
|
||||
// </Button>
|
||||
<Button variant="secondary" size="sm" className={'question-option'} id={`button_option_${i}`} key={`button_option_${i}`} onClick={() =>
|
||||
this.clicked_mini_answer(minivis[this.state.current_mini_index]['type'], minivis[this.state.current_mini_index]['question'], item, minivis[this.state.current_mini_index]['correct_answer'], 'timeTaken')}>
|
||||
{item}
|
||||
</Button>
|
||||
)
|
||||
let VisComp = minivis[this.state.current_mini_index]['vis']
|
||||
//console.log(VisComp)
|
||||
return (
|
||||
<Container className={'container-class'} fluid>
|
||||
<Row className={'vis-quiz-row'}>
|
||||
<Col lg={6} className={'vis-column'}>
|
||||
<VisComp width={window.innerWidth} height={window.innerHeight} resized={this.state.resize_bool}></VisComp>
|
||||
</Col>
|
||||
<Col lg={6} className={'quiz-column'}>
|
||||
<div className='timeStamp'>
|
||||
<Countdown date={Date.now() + 25000} renderer={({ minutes, seconds, completed }) => {
|
||||
return <span>Time Remaining: {minutes}:{seconds}</span>;
|
||||
}} autoStart={true} key={Date.now()} onComplete={() => this.minitimeout()} />
|
||||
{/* <CountDownTimer hoursMinSecs={hoursMinSecs} /> */}
|
||||
</div>
|
||||
<div className={'question-container'}>
|
||||
<div className={'question-text'}>
|
||||
<p>{minivis[this.state.current_mini_index]['question']}</p>
|
||||
</div>
|
||||
|
||||
<div className={'question-options d-grid gap-2 btn-block'}>
|
||||
{options}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
<Row className={'progress-bar-row'}>
|
||||
<ProgressBar completed={(parseInt(this.state.current_mini_index)).toString()} maxCompleted={num.toString()} length={Math.min(window.innerWidth, window.innerHeight)} />
|
||||
</Row>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<>
|
||||
<Row className={'justify-content-center no-margin-row'}>
|
||||
<Col lg={6} className={'text-box text-justify'}>
|
||||
|
||||
|
||||
<Form.Group className={'question'}>
|
||||
<Form.Label>Please select your age.</Form.Label>
|
||||
<Form.Select as="select" id={'age'} onChange={this.handleDemographicChange.bind(this)}>
|
||||
<option value={null} selected={true} disabled={true}></option>
|
||||
{ages.map((d, i) => (
|
||||
<option key={d} value={d}>{d}</option>
|
||||
))}
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
<hr />
|
||||
|
||||
<Form.Group className={'question'}>
|
||||
<Form.Label>Please select your gender.</Form.Label>
|
||||
<Form.Select as="select" id={'sex'} onChange={this.handleDemographicChange.bind(this)}>
|
||||
<option value={null} selected={true} disabled={true}></option>
|
||||
<option key={'male'} value={'male'}>Male</option>
|
||||
<option key={'female'} value={'female'}>Female</option>
|
||||
<option key={'other'} value={'other'}>Other</option>
|
||||
<option key={'withdraw'} value={'withdraw'}>I do not wish to disclose.</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
<hr />
|
||||
|
||||
<Form.Group className={'question'}>
|
||||
<Form.Label>Please select your highest level of completed education.</Form.Label>
|
||||
<Form.Select as="select" id={'education'} onChange={this.handleDemographicChange.bind(this)}>
|
||||
<option value={null} selected={true} disabled={true}></option>
|
||||
<option value={'highschool'}>High School Diploma / GED</option>
|
||||
<option value={'associate'}>Associate Degree</option>
|
||||
<option value={'bachelors'}>Bachelors Degree</option>
|
||||
<option value={'masters'}>Masters Degree</option>
|
||||
<option value={'doctorate'}>Doctorate Degree</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
<hr />
|
||||
<Form.Group className={'question'}>
|
||||
<Form.Label>Are you color-blind?</Form.Label>
|
||||
<Form.Select as="select" id={'color-blind'} onChange={this.handleDemographicChange.bind(this)}>
|
||||
<option value={null} selected={true} disabled={true}></option>
|
||||
<option value={'yes'}>Yes</option>
|
||||
<option value={'no'}>No</option>
|
||||
<option value={'maybe'}>I do not wish to disclose.</option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
<hr />
|
||||
|
||||
<Form.Group className={'question'}>
|
||||
<Form.Label>Please select your familiarity with visualization.</Form.Label>
|
||||
<Form.Select as="select" id={'familiarity'} onChange={this.handleDemographicChange.bind(this)}>
|
||||
<option value={null} selected={true} disabled={true}></option>
|
||||
<option value={'not_familiar'}>I have never created a visualization.</option>
|
||||
<option value={'somewhat'}>I am somewhat familiar.</option>
|
||||
<option value={'very_familiar'}>I have created visualization systems before. </option>
|
||||
</Form.Select>
|
||||
</Form.Group>
|
||||
<hr />
|
||||
|
||||
|
||||
<Form.Group>
|
||||
<Form.Label>Please include any additional comments below. (optional)</Form.Label>
|
||||
<Form.Control as="textarea" id={'comments'} rows={3} onChange={this.handleTextChange.bind(this)}>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
<hr />
|
||||
|
||||
|
||||
<div className={'text-center'}><Button className={'btn-sm'}
|
||||
variant={"success"}
|
||||
onClick={this.on_survey_click.bind(this)}
|
||||
disabled={(this.state.form_incomplete || this.state.demographics_incomplete)}
|
||||
id={'survey_submit-btn'}>
|
||||
Submit Responses
|
||||
</Button></div>
|
||||
|
||||
<p className={'text-box'}></p>
|
||||
</Col>
|
||||
|
||||
</Row>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default VisQuiz;
|
||||
export { correct_collect };
|
||||
export { wrong_collect };
|
||||
export { score_1 };
|
||||
export { score_2 };
|
||||
13
ReactTool/frontend/src/reportWebVitals.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const reportWebVitals = onPerfEntry => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||