mirror of
https://github.com/olehomelchenko/minivlat-local-ua.git
synced 2025-12-21 13:12:23 +00:00
init
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
node_modules/
|
||||
responses.json
|
||||
.env
|
||||
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# local mini-VLAT
|
||||
|
||||
This project is a simple web application designed to collect responses from users through a randomized quiz format. The application consists of several pages, including a consent page, a quiz page, a questionnaire, and a results page.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── public
|
||||
│ ├── index.html # Main entry point for the web application
|
||||
│ ├── consent.html # Consent page for users
|
||||
│ ├── quiz.html # Quiz page that loads questions dynamically
|
||||
│ ├── questionnaire.html # Questionnaire for additional participant information
|
||||
│ └── results.html # Results page displaying quiz outcomes
|
||||
├── src
|
||||
│ ├── js
|
||||
│ │ ├── app.js # Main JavaScript file for app initialization and routing
|
||||
│ │ ├── consent.js # JavaScript logic for the consent page
|
||||
│ │ ├── quiz.js # JavaScript for managing quiz functionality
|
||||
│ │ ├── questionnaire.js # Logic for the questionnaire
|
||||
│ │ └── results.js # Processing and displaying quiz results
|
||||
│ ├── css
|
||||
│ │ └── styles.css # Styles for the web application
|
||||
│ └── data
|
||||
│ └── questions.json # Questions and answers in nested JSON format
|
||||
├── package.json # npm configuration file
|
||||
├── server.js # Simple backend server for handling requests
|
||||
└── README.md # Documentation for the project
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Consent Page**: Users can read consent information and proceed to the quiz.
|
||||
- **Randomized Quiz**: Users are randomly assigned one of four quiz versions.
|
||||
- **Dynamic Question Loading**: Questions are loaded from a JSON file based on the assigned quiz version.
|
||||
- **Questionnaire**: A follow-up questionnaire collects additional information from participants.
|
||||
- **Results Display**: Users can view their quiz results, including correct and incorrect answers.
|
||||
|
||||
## Setup Instructions
|
||||
|
||||
1. Clone the repository to your local machine.
|
||||
2. Navigate to the project directory.
|
||||
3. Install the necessary dependencies using npm:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
4. Start the server:
|
||||
```
|
||||
node server.js
|
||||
```
|
||||
5. Open your web browser and go to `http://localhost:3000` to access the application.
|
||||
|
||||
## Contributing
|
||||
|
||||
Feel free to submit issues or pull requests for any improvements or bug fixes.
|
||||
33
docker-compose.yml
Normal file
33
docker-compose.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
web:
|
||||
container_name: mini-vlat-adaptation
|
||||
image: node:14
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app
|
||||
- ./data:/app/data
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- PORT=3000
|
||||
env_file:
|
||||
- .env
|
||||
command: sh -c "npm install && npm start"
|
||||
|
||||
traefik:
|
||||
image: traefik:v2.5
|
||||
container_name: traefik
|
||||
ports:
|
||||
- "80:80"
|
||||
- "8080:8080"
|
||||
command:
|
||||
- "--api.insecure=true"
|
||||
- "--providers.docker=true"
|
||||
- "--entrypoints.web.address=:80"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
labels:
|
||||
- "traefik.http.routers.web.rule=Host(`${YOUR_DOMAIN}`)"
|
||||
- "traefik.http.services.web.loadbalancer.server.port=3000"
|
||||
582
package-lock.json
generated
Normal file
582
package-lock.json
generated
Normal file
@@ -0,0 +1,582 @@
|
||||
{
|
||||
"name": "simple-web-app",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||
"requires": {
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
}
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.7.9",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
|
||||
"integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.20.3",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
|
||||
"integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"content-type": "~1.0.5",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "2.4.1",
|
||||
"qs": "6.13.0",
|
||||
"raw-body": "2.5.2",
|
||||
"type-is": "~1.6.18",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
|
||||
},
|
||||
"call-bind-apply-helpers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
|
||||
"integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
|
||||
"requires": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"call-bound": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
|
||||
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
|
||||
"requires": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"get-intrinsic": "^1.2.6"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.2.1"
|
||||
}
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
||||
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
|
||||
"integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||
},
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
|
||||
},
|
||||
"dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"requires": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
|
||||
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="
|
||||
},
|
||||
"es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
|
||||
},
|
||||
"es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
|
||||
},
|
||||
"es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"requires": {
|
||||
"es-errors": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
||||
},
|
||||
"etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.21.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||
"integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.3",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.7.1",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.3.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"merge-descriptors": "1.0.3",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.12",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.13.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.2.1",
|
||||
"send": "0.19.0",
|
||||
"serve-static": "1.16.2",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
|
||||
"integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "2.0.1",
|
||||
"unpipe": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.9",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
|
||||
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
|
||||
},
|
||||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
|
||||
"integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
|
||||
"requires": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.0.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.0",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"requires": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
|
||||
},
|
||||
"hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"requires": {
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||
},
|
||||
"math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
|
||||
},
|
||||
"merge-descriptors": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
||||
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.13.3",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
|
||||
"integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA=="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
|
||||
"integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
|
||||
"requires": {
|
||||
"forwarded": "0.2.0",
|
||||
"ipaddr.js": "1.9.1"
|
||||
}
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
|
||||
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
|
||||
"requires": {
|
||||
"side-channel": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.19.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
|
||||
"integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "2.4.1",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.16.2",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
|
||||
"integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
|
||||
"requires": {
|
||||
"encodeurl": "~2.0.0",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.19.0"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||
},
|
||||
"side-channel": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
|
||||
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
|
||||
"requires": {
|
||||
"es-errors": "^1.3.0",
|
||||
"object-inspect": "^1.13.3",
|
||||
"side-channel-list": "^1.0.0",
|
||||
"side-channel-map": "^1.0.1",
|
||||
"side-channel-weakmap": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"side-channel-list": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
|
||||
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
|
||||
"requires": {
|
||||
"es-errors": "^1.3.0",
|
||||
"object-inspect": "^1.13.3"
|
||||
}
|
||||
},
|
||||
"side-channel-map": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
|
||||
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
|
||||
"requires": {
|
||||
"call-bound": "^1.0.2",
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.5",
|
||||
"object-inspect": "^1.13.3"
|
||||
}
|
||||
},
|
||||
"side-channel-weakmap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
|
||||
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
|
||||
"requires": {
|
||||
"call-bound": "^1.0.2",
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.5",
|
||||
"object-inspect": "^1.13.3",
|
||||
"side-channel-map": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
17
package.json
Normal file
17
package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "simple-web-app",
|
||||
"version": "1.0.0",
|
||||
"description": "A simple web app for collecting responses through a quiz and storing results.",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.9",
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
18
public/consent.html
Normal file
18
public/consent.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Consent Page</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Consent Form</h1>
|
||||
<p>Please read the following consent information carefully before proceeding:</p>
|
||||
<p>Your participation in this quiz is voluntary, and you can withdraw at any time. Your responses will be kept confidential.</p>
|
||||
<button id="consentButton">I Consent to Participate</button>
|
||||
</div>
|
||||
<script src="js/consent.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
36
public/index.html
Normal file
36
public/index.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="uk">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Consent Page</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
<script src="js/app.js" defer></script>
|
||||
<script src="js/consent.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Згода на участь в дослідженні</h1>
|
||||
<p>
|
||||
Запрошуємо взяти участь в дослідженні з адаптації інструменту оцінки грамотності в візуалізації даних, яке проводять викладачі та студенти Київської школи економіки.
|
||||
</p>
|
||||
<p>
|
||||
Мета дослідження полягає в адаптації інструменту, який вимірює, наскільки вдало люди можуть розуміти, інтерпретувати та використовувати дані, що містяться в візуалізаціях (графіки, діаграми тощо), для вирішення повсякденних проблем.
|
||||
</p>
|
||||
<p>
|
||||
Вам буде запропоновано 12 різних типів візуалізацій даних. Кожен з них буде супроводжений запитанням, відповідь на яке потрібно дати, засновуючись на інформації що отримана із візуалізації. Мова опитування буде обрана випадковим чином із двох: українська або англійська. Оберіть відповідь, яку вважаєте найточнішою. Якщо ви не впевнені, оберіть “пропустити” замість того щоб вгадувати. На кожне запитання ви маєте 25 секунд для відповіді. Якщо ви не встигли відповісти, тест автоматично перейде до наступного запитання.
|
||||
</p>
|
||||
<p>
|
||||
Після надання відповідей ми попросимо вас також заповнити коротку демографічну анкету. Дані, що ми зберемо протягом опитування, є анонімними та не зможуть бути використані для ідентифікації вашої особи. Вони будуть використані в поточному та подальших дослідженнях грамотності в сфері візуалізації даних. Ці дані можуть бути передані іншим дослідникам/цям, що проводять дослідження в цій або суміжних сферах. Також вони будуть опубліковані в репозиторіях для ширшого доступу наукової спільноти.
|
||||
</p>
|
||||
<p>
|
||||
Якщо ви маєте будь-які питання щодо змісту та деталей дослідження, звʼяжіться з Олегом Омельченком o_omelchenko@kse.org.ua.
|
||||
</p>
|
||||
<p>
|
||||
Дякуємо за допомогу в проведенні дослідження!
|
||||
</p>
|
||||
|
||||
<button id="consentButton">Погоджуюсь з умовами, розпочати тест</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
101
public/questionnaire.html
Normal file
101
public/questionnaire.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Questionnaire</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Анкета учасника(ці)</h1>
|
||||
<div id="error-message" style="display: none; color: red; margin-bottom: 1rem;"></div>
|
||||
<form id="questionnaire-form">
|
||||
<label for="age">Вік:</label>
|
||||
<input type="number" id="age" name="age" required min="10" max="100">
|
||||
|
||||
<label for="gender">Ґендер:</label>
|
||||
<select id="gender" name="gender" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="male">Чоловік</option>
|
||||
<option value="female">Жінка</option>
|
||||
<option value="other">Небінарна персона / Інше</option>
|
||||
<option value="prefer_not_to_say">Не бажаю відповідати</option>
|
||||
</select>
|
||||
|
||||
<label for="education">Найвищий здобутий рівень освіти:</label>
|
||||
<select id="education" name="education" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="highschool">Середня школа</option>
|
||||
<option value="bachelors">Бакалавр</option>
|
||||
<option value="masters">Магістр</option>
|
||||
<option value="doctorate">Доктор наук</option>
|
||||
</select>
|
||||
|
||||
<label for="color-blind">Чи маєте ви дальтонізм (кольорову сліпоту)?</label>
|
||||
<select id="color-blind" name="color-blind" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="yes">Так</option>
|
||||
<option value="no">Ні</option>
|
||||
<option value="maybe">Не бажаю відповідати</option>
|
||||
</select>
|
||||
|
||||
<label for="familiarity">Ваш досвід роботи з візуалізацією даних:</label>
|
||||
<select id="familiarity" name="familiarity" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="not_familiar">Я ніколи не працював професійно з візуалізацією даних</option>
|
||||
<option value="somewhat">Я дещо знайомий з візуалізацією даних</option>
|
||||
<option value="very_familiar">Я сам створював візуалізації даних</option>
|
||||
</select>
|
||||
|
||||
<label for="english-level">Рівень англійської мови:</label>
|
||||
<select id="english-level" name="english-level" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="beginner">Початковий</option>
|
||||
<option value="intermediate">Середній</option>
|
||||
<option value="advanced">Високий</option>
|
||||
<option value="native">Рідна мова</option>
|
||||
</select>
|
||||
|
||||
<label for="ukrainian-level">Рівень української мови:</label>
|
||||
<select id="ukrainian-level" name="ukrainian-level" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="beginner">Початковий</option>
|
||||
<option value="intermediate">Середній</option>
|
||||
<option value="advanced">Високий</option>
|
||||
<option value="native">Рідна мова</option>
|
||||
</select>
|
||||
|
||||
<label for="visualization-difficulty">Наскільки складно вам було сприймати зміст візуалізацій (графіків):</label>
|
||||
<select id="visualization-difficulty" name="visualization-difficulty" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="easy">Легко</option>
|
||||
<option value="moderate">Помірно</option>
|
||||
<option value="difficult">Важко</option>
|
||||
</select>
|
||||
|
||||
<label for="quiz-difficulty">Наскільки складно вам було сприймати зміст питань тесту:</label>
|
||||
<select id="quiz-difficulty" name="quiz-difficulty" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="easy">Легко</option>
|
||||
<option value="moderate">Помірно</option>
|
||||
<option value="difficult">Важко</option>
|
||||
</select>
|
||||
|
||||
<label for="kse-affiliation">Ви студент(ка), викладач(ка)/співробітник(ця) Київської школи економіки?</label>
|
||||
<select id="kse-affiliation" name="kse-affiliation" required>
|
||||
<option value="" selected disabled></option>
|
||||
<option value="neither">Ні</option>
|
||||
<option value="student">Студент(ка)</option>
|
||||
<option value="teacher_employee">Викладач(ка)/Співробітник(ця)</option>
|
||||
</select>
|
||||
|
||||
<label for="comments">Додаткові коментарі:</label>
|
||||
<textarea id="comments" name="comments" rows="4"></textarea>
|
||||
|
||||
<button type="submit">Надіслати</button>
|
||||
</form>
|
||||
</div>
|
||||
<script src="js/questionnaire.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
27
public/quiz.html
Normal file
27
public/quiz.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Quiz</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
<script src="js/quiz.js" defer></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="quiz-container">
|
||||
<div id="timer">Time remaining: <span id="time">25</span>s</div>
|
||||
<div id="quiz" style="display: flex;">
|
||||
<div id="chart" style="flex: 1; display: flex; justify-content: center; align-items: center;"></div>
|
||||
<div style="flex: 1; display: flex; flex-direction: column; justify-content: center; align-items: center;">
|
||||
<div id="question-text"></div>
|
||||
<div id="options"></div>
|
||||
<!-- Removed submit button -->
|
||||
</div>
|
||||
</div>
|
||||
<div id="results"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
30
public/results.html
Normal file
30
public/results.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="uk">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Результати тесту</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 id="results-header"></h1>
|
||||
<div class="results">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Питання</th>
|
||||
<th>Тип діаграми</th>
|
||||
<th>Коректність</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="results-table-body">
|
||||
<!-- Dynamic content will be inserted here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button onclick="window.location.href='index.html'">Повернутися на головну</button>
|
||||
</div>
|
||||
<script src="js/results.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
55
server.js
Normal file
55
server.js
Normal file
@@ -0,0 +1,55 @@
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const axios = require('axios');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
const WEBHOOK_URL = process.env.WEBHOOK_URL;
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
app.use(express.static(path.join(__dirname, 'src')));
|
||||
|
||||
let responses = [];
|
||||
|
||||
// Endpoint to store responses
|
||||
app.post('/api/responses', (req, res) => {
|
||||
const response = req.body;
|
||||
responses.push(response);
|
||||
fs.writeFileSync('data/responses.json', JSON.stringify(responses, null, 2));
|
||||
console.log('Received response:', response);
|
||||
|
||||
// Redirect payload to webhook
|
||||
if (WEBHOOK_URL) {
|
||||
axios.post(WEBHOOK_URL, JSON.stringify(response), {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
console.log('Payload sent to webhook successfully');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error sending payload to webhook:', error);
|
||||
});
|
||||
}
|
||||
|
||||
res.status(201).json({ success: true, message: 'Response stored successfully' });
|
||||
});
|
||||
|
||||
// Endpoint to retrieve questions
|
||||
app.get('/api/questions', (req, res) => {
|
||||
const questionsPath = path.join(__dirname, 'src', 'data', 'questions.json');
|
||||
fs.readFile(questionsPath, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
return res.status(500).send('Error reading questions');
|
||||
}
|
||||
res.json(JSON.parse(data));
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server is running on http://localhost:${PORT}`);
|
||||
});
|
||||
160
src/charts/areachart-original.vl.json
Normal file
160
src/charts/areachart-original.vl.json
Normal file
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Robusta Coffee Price",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"data": {
|
||||
"values": [
|
||||
{
|
||||
"month": "2018-01",
|
||||
"price": 0.8865
|
||||
},
|
||||
{
|
||||
"month": "2018-02",
|
||||
"price": 0.8924
|
||||
},
|
||||
{
|
||||
"month": "2018-03",
|
||||
"price": 0.8818
|
||||
},
|
||||
{
|
||||
"month": "2018-04",
|
||||
"price": 0.8831
|
||||
},
|
||||
{
|
||||
"month": "2018-05",
|
||||
"price": 0.8874
|
||||
},
|
||||
{
|
||||
"month": "2018-06",
|
||||
"price": 0.8607
|
||||
},
|
||||
{
|
||||
"month": "2018-07",
|
||||
"price": 0.8442
|
||||
},
|
||||
{
|
||||
"month": "2018-08",
|
||||
"price": 0.8074
|
||||
},
|
||||
{
|
||||
"month": "2018-09",
|
||||
"price": 0.7670
|
||||
},
|
||||
{
|
||||
"month": "2018-10",
|
||||
"price": 0.8532
|
||||
},
|
||||
{
|
||||
"month": "2018-11",
|
||||
"price": 0.8352
|
||||
},
|
||||
{
|
||||
"month": "2018-12",
|
||||
"price": 0.7757
|
||||
},
|
||||
{
|
||||
"month": "2019-01",
|
||||
"price": 0.7824
|
||||
},
|
||||
{
|
||||
"month": "2019-02",
|
||||
"price": 0.7865
|
||||
},
|
||||
{
|
||||
"month": "2019-03",
|
||||
"price": 0.7696
|
||||
},
|
||||
{
|
||||
"month": "2019-04",
|
||||
"price": 0.7328
|
||||
},
|
||||
{
|
||||
"month": "2019-05",
|
||||
"price": 0.7112
|
||||
},
|
||||
{
|
||||
"month": "2019-06",
|
||||
"price": 0.7402
|
||||
},
|
||||
{
|
||||
"month": "2019-07",
|
||||
"price": 0.7393
|
||||
},
|
||||
{
|
||||
"month": "2019-08",
|
||||
"price": 0.7078
|
||||
},
|
||||
{
|
||||
"month": "2019-09",
|
||||
"price": 0.7064
|
||||
},
|
||||
{
|
||||
"month": "2019-10",
|
||||
"price": 0.6863
|
||||
},
|
||||
{
|
||||
"month": "2019-11",
|
||||
"price": 0.7328
|
||||
},
|
||||
{
|
||||
"month": "2019-12",
|
||||
"price": 0.7322
|
||||
}
|
||||
]
|
||||
},
|
||||
"mark": {
|
||||
"type": "area",
|
||||
"color": "#3182bd",
|
||||
"opacity": 0.6,
|
||||
"line": true,
|
||||
"strokeWidth": 1.5
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "month",
|
||||
"type": "temporal",
|
||||
"title": null,
|
||||
"axis": {
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "price",
|
||||
"type": "quantitative",
|
||||
"title": "Coffee Price ($/lb)",
|
||||
"axis": {
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"tooltip": [
|
||||
{
|
||||
"field": "month",
|
||||
"type": "temporal",
|
||||
"title": "Month"
|
||||
},
|
||||
{
|
||||
"field": "price",
|
||||
"type": "quantitative",
|
||||
"title": "Price",
|
||||
"format": "$.3f"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridOpacity": 0.5,
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
160
src/charts/areachart-ukrainian.vl.json
Normal file
160
src/charts/areachart-ukrainian.vl.json
Normal file
@@ -0,0 +1,160 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Ціна кави Робуста",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"data": {
|
||||
"values": [
|
||||
{
|
||||
"month": "2018-01",
|
||||
"price": 0.8865
|
||||
},
|
||||
{
|
||||
"month": "2018-02",
|
||||
"price": 0.8924
|
||||
},
|
||||
{
|
||||
"month": "2018-03",
|
||||
"price": 0.8818
|
||||
},
|
||||
{
|
||||
"month": "2018-04",
|
||||
"price": 0.8831
|
||||
},
|
||||
{
|
||||
"month": "2018-05",
|
||||
"price": 0.8874
|
||||
},
|
||||
{
|
||||
"month": "2018-06",
|
||||
"price": 0.8607
|
||||
},
|
||||
{
|
||||
"month": "2018-07",
|
||||
"price": 0.8442
|
||||
},
|
||||
{
|
||||
"month": "2018-08",
|
||||
"price": 0.8074
|
||||
},
|
||||
{
|
||||
"month": "2018-09",
|
||||
"price": 0.7670
|
||||
},
|
||||
{
|
||||
"month": "2018-10",
|
||||
"price": 0.8532
|
||||
},
|
||||
{
|
||||
"month": "2018-11",
|
||||
"price": 0.8352
|
||||
},
|
||||
{
|
||||
"month": "2018-12",
|
||||
"price": 0.7757
|
||||
},
|
||||
{
|
||||
"month": "2019-01",
|
||||
"price": 0.7824
|
||||
},
|
||||
{
|
||||
"month": "2019-02",
|
||||
"price": 0.7865
|
||||
},
|
||||
{
|
||||
"month": "2019-03",
|
||||
"price": 0.7696
|
||||
},
|
||||
{
|
||||
"month": "2019-04",
|
||||
"price": 0.7328
|
||||
},
|
||||
{
|
||||
"month": "2019-05",
|
||||
"price": 0.7112
|
||||
},
|
||||
{
|
||||
"month": "2019-06",
|
||||
"price": 0.7402
|
||||
},
|
||||
{
|
||||
"month": "2019-07",
|
||||
"price": 0.7393
|
||||
},
|
||||
{
|
||||
"month": "2019-08",
|
||||
"price": 0.7078
|
||||
},
|
||||
{
|
||||
"month": "2019-09",
|
||||
"price": 0.7064
|
||||
},
|
||||
{
|
||||
"month": "2019-10",
|
||||
"price": 0.6863
|
||||
},
|
||||
{
|
||||
"month": "2019-11",
|
||||
"price": 0.7328
|
||||
},
|
||||
{
|
||||
"month": "2019-12",
|
||||
"price": 0.7322
|
||||
}
|
||||
]
|
||||
},
|
||||
"mark": {
|
||||
"type": "area",
|
||||
"color": "#3182bd",
|
||||
"opacity": 0.6,
|
||||
"line": true,
|
||||
"strokeWidth": 1.5
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "month",
|
||||
"type": "temporal",
|
||||
"title": null,
|
||||
"axis": {
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "price",
|
||||
"type": "quantitative",
|
||||
"title": "Ціна кави ($/фунт)",
|
||||
"axis": {
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"tooltip": [
|
||||
{
|
||||
"field": "month",
|
||||
"type": "temporal",
|
||||
"title": "Month"
|
||||
},
|
||||
{
|
||||
"field": "price",
|
||||
"type": "quantitative",
|
||||
"title": "Price",
|
||||
"format": "$.3f"
|
||||
}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridOpacity": 0.5,
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/charts/barchart-original.vl.json
Normal file
37
src/charts/barchart-original.vl.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Global Internet Speed (Mbps)",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"data": {
|
||||
"url": "data/barchart.csv", "format": {"type": "csv"}
|
||||
},
|
||||
"width": "container",
|
||||
"height": "container",
|
||||
"mark": {
|
||||
"type": "bar"
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Country",
|
||||
"type": "nominal",
|
||||
"axis": {
|
||||
"labelAngle": 40,
|
||||
"labelAlign": "left",
|
||||
"title": null,
|
||||
"labelPadding": 10
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "Speed",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Internet Speed (Mbps)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/charts/barchart-ukrainian.vl.json
Normal file
38
src/charts/barchart-ukrainian.vl.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Світова швидкість інтернету (МБіт/с)",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"data": {
|
||||
"url": "data/barchart.csv", "format": {"type": "csv"}
|
||||
},
|
||||
"width": "container",
|
||||
"height": "container",
|
||||
"mark": {
|
||||
"type": "bar"
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Country_UK",
|
||||
"type": "nominal",
|
||||
"title": "Країна",
|
||||
"axis": {
|
||||
"labelAngle": 40,
|
||||
"labelAlign": "left",
|
||||
"title": null,
|
||||
"labelPadding": 10
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "Speed",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Швидкість інтернету (МБіт/с)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
82
src/charts/bubblechart-original.vl.json
Normal file
82
src/charts/bubblechart-original.vl.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Metro Systems of the World",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 400,
|
||||
"height": 400,
|
||||
"data": {
|
||||
"url": "data/bubblechart.csv"
|
||||
},
|
||||
"layer": [
|
||||
{
|
||||
"mark": {
|
||||
"type": "circle",
|
||||
"opacity": 0.7,
|
||||
"stroke": "black",
|
||||
"strokeWidth": 1,
|
||||
"fill": "#3182bd"
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "NumberofStations",
|
||||
"type": "quantitative",
|
||||
"scale": {"domain": [150, 800]},
|
||||
"axis": {
|
||||
"title": "Number of Stations",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "Length",
|
||||
"type": "quantitative",
|
||||
"scale": {"domain": [150, 500]},
|
||||
"axis": {
|
||||
"title": "Total System Length (Km)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"field": "Ridership",
|
||||
"type": "quantitative",
|
||||
"scale": {
|
||||
"domain": [0, 5],
|
||||
"range": [0, 1500]
|
||||
},
|
||||
"legend": {
|
||||
"title": "Ridership (bn per year)",
|
||||
"orient": "right",
|
||||
"symbolType": "circle",
|
||||
"values": [1.5, 2.5, 3.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"mark": {
|
||||
"type": "text",
|
||||
"fontSize": 11,
|
||||
"dx": 15,
|
||||
"align": "left"
|
||||
},
|
||||
"encoding": {
|
||||
"x": {"field": "NumberofStations", "type": "quantitative"},
|
||||
"y": {"field": "Length", "type": "quantitative"},
|
||||
"text": {"field": "City", "type": "nominal"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridDash": [1, 1],
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {"stroke": null}
|
||||
}
|
||||
}
|
||||
82
src/charts/bubblechart-ukrainian.vl.json
Normal file
82
src/charts/bubblechart-ukrainian.vl.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Системи метро світу",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 400,
|
||||
"height": 400,
|
||||
"data": {
|
||||
"url": "data/bubblechart.csv"
|
||||
},
|
||||
"layer": [
|
||||
{
|
||||
"mark": {
|
||||
"type": "circle",
|
||||
"opacity": 0.7,
|
||||
"stroke": "black",
|
||||
"strokeWidth": 1,
|
||||
"fill": "#3182bd"
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "NumberofStations",
|
||||
"type": "quantitative",
|
||||
"scale": {"domain": [150, 800]},
|
||||
"axis": {
|
||||
"title": "Кількість станцій",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "Length",
|
||||
"type": "quantitative",
|
||||
"scale": {"domain": [150, 500]},
|
||||
"axis": {
|
||||
"title": "Загальна довжина системи (км)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"size": {
|
||||
"field": "Ridership",
|
||||
"type": "quantitative",
|
||||
"scale": {
|
||||
"domain": [0, 5],
|
||||
"range": [0, 1500]
|
||||
},
|
||||
"legend": {
|
||||
"title": "Пасажиропотік (млрд на рік)",
|
||||
"orient": "right",
|
||||
"symbolType": "circle",
|
||||
"values": [1.5, 2.5, 3.5]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"mark": {
|
||||
"type": "text",
|
||||
"fontSize": 11,
|
||||
"dx": 15,
|
||||
"align": "left"
|
||||
},
|
||||
"encoding": {
|
||||
"x": {"field": "NumberofStations", "type": "quantitative"},
|
||||
"y": {"field": "Length", "type": "quantitative"},
|
||||
"text": {"field": "CityUK", "type": "nominal"}
|
||||
}
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridDash": [1, 1],
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {"stroke": null}
|
||||
}
|
||||
}
|
||||
113
src/charts/choropleth-original.vl.json
Normal file
113
src/charts/choropleth-original.vl.json
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Unemployment Rates for States in 2020",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 500,
|
||||
"projection": {
|
||||
"type": "albersUsa"
|
||||
},
|
||||
"layer": [
|
||||
{
|
||||
"data": {
|
||||
"url": "data/topo-USA.json",
|
||||
"format": {
|
||||
"type": "topojson",
|
||||
"feature": "states"
|
||||
}
|
||||
},
|
||||
"transform": [
|
||||
{
|
||||
"lookup": "id",
|
||||
"from": {
|
||||
"data": {
|
||||
"url": "data/choropleth.csv"
|
||||
},
|
||||
"key": "id",
|
||||
"fields": ["rate"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"mark": {
|
||||
"type": "geoshape",
|
||||
"stroke": "#fff",
|
||||
"strokeWidth": 0.5
|
||||
},
|
||||
"encoding": {
|
||||
"color": {
|
||||
"field": "rate",
|
||||
"type": "quantitative",
|
||||
"title": "Unemployment Rate (%)",
|
||||
"scale": {
|
||||
"scheme": "blues"
|
||||
},
|
||||
"legend": {
|
||||
"title": "Unemployment Rate (%)",
|
||||
"orient": "top",
|
||||
"direction": "horizontal"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"url": "data/topo-USA.json",
|
||||
"format": {
|
||||
"type": "topojson",
|
||||
"feature": "states"
|
||||
}
|
||||
},
|
||||
"mark": {
|
||||
"type": "geoshape",
|
||||
"filled": false,
|
||||
"stroke": "#ccc",
|
||||
"strokeWidth": 0.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"url": "data/choropleth.csv"
|
||||
},
|
||||
"transform": [
|
||||
{
|
||||
"lookup": "code",
|
||||
"from": {
|
||||
"data": {
|
||||
"url": "data/state-coordinates.json"
|
||||
},
|
||||
"key": "code",
|
||||
"fields": ["latitude", "longitude"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"mark": {
|
||||
"type": "text",
|
||||
"color": "black",
|
||||
"fontSize": 10,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"encoding": {
|
||||
"longitude": {
|
||||
"field": "longitude",
|
||||
"type": "quantitative"
|
||||
},
|
||||
"latitude": {
|
||||
"field": "latitude",
|
||||
"type": "quantitative"
|
||||
},
|
||||
"text": {
|
||||
"field": "code",
|
||||
"type": "nominal"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
308
src/charts/choropleth-ukrainian.vl.json
Normal file
308
src/charts/choropleth-ukrainian.vl.json
Normal file
@@ -0,0 +1,308 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"height": 300,
|
||||
"width": 600,
|
||||
"title": "Кількість шлюбів в першому півріччі 2024 р.",
|
||||
"config": {
|
||||
"padding": 0,
|
||||
"legend": {
|
||||
"orient": "top",
|
||||
"padding": 20,
|
||||
"gradientLength": 300,
|
||||
"titleFontWeight": "normal",
|
||||
"titleAlign": "center",
|
||||
"titleAnchor": "middle",
|
||||
"titleLimit": 1000
|
||||
}
|
||||
},
|
||||
"layer": [
|
||||
{
|
||||
"data": {
|
||||
"url": "https://raw.githubusercontent.com/org-scn-design-studio-community/sdkcommunitymaps/master/geojson/Europe/Ukraine-regions.json",
|
||||
"format": {
|
||||
"feature": "UKR_adm1",
|
||||
"type": "topojson"
|
||||
}
|
||||
},
|
||||
"mark": {
|
||||
"type": "geoshape",
|
||||
"stroke": "white",
|
||||
"strokeOpacity": 0.3,
|
||||
"strokeWidth": 0.5
|
||||
},
|
||||
"encoding": {
|
||||
"color": {
|
||||
"field": "value",
|
||||
"legend": {
|
||||
"title": null
|
||||
},
|
||||
"scale": {
|
||||
"scheme": "blues",
|
||||
"reverse": false
|
||||
},
|
||||
"type": "quantitative"
|
||||
}
|
||||
},
|
||||
"projection": {
|
||||
"type": "mercator"
|
||||
},
|
||||
"transform": [
|
||||
{
|
||||
"lookup": "properties.ID_1",
|
||||
"from": {
|
||||
"data": {
|
||||
"name": "referendum"
|
||||
},
|
||||
"key": "id",
|
||||
"fields": [
|
||||
"value"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"name": "referendum"
|
||||
},
|
||||
"mark": {
|
||||
"type": "text",
|
||||
"color": "#111"
|
||||
},
|
||||
"encoding": {
|
||||
"latitude": {
|
||||
"field": "lat",
|
||||
"type": "quantitative"
|
||||
},
|
||||
"longitude": {
|
||||
"field": "lon",
|
||||
"type": "quantitative"
|
||||
},
|
||||
"text": {
|
||||
"field": "short_region",
|
||||
"type": "ordinal"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"datasets": {
|
||||
"referendum": [
|
||||
{
|
||||
"region": "Львівська область",
|
||||
"short_region": "Льв",
|
||||
"id": 3150,
|
||||
"value": 4616,
|
||||
"lat": 49.8397,
|
||||
"lon": 24.0297
|
||||
},
|
||||
{
|
||||
"region": "Івано-Франківська область",
|
||||
"short_region": "ІвФ",
|
||||
"id": 3142,
|
||||
"value": 2333,
|
||||
"lat": 48.7226,
|
||||
"lon": 24.7105
|
||||
},
|
||||
{
|
||||
"region": "Тернопільська область",
|
||||
"short_region": "Тер",
|
||||
"id": 3157,
|
||||
"value": "1512",
|
||||
"lat": 49.3535,
|
||||
"lon": 25.5948
|
||||
},
|
||||
{
|
||||
"region": "м.Київ",
|
||||
"short_region": "м.К",
|
||||
"id": 3147,
|
||||
"value": 9392,
|
||||
"lat": 50.4501,
|
||||
"lon": 30.5234
|
||||
},
|
||||
{
|
||||
"region": "Волинська область",
|
||||
"short_region": "Вол",
|
||||
"id": 3160,
|
||||
"value": 1791,
|
||||
"lat": 51.3424,
|
||||
"lon": 25
|
||||
},
|
||||
{
|
||||
"region": "Рівненська область",
|
||||
"short_region": "Рів",
|
||||
"id": 3154,
|
||||
"value": 2682,
|
||||
"lat": 51,
|
||||
"lon": 26.8
|
||||
},
|
||||
{
|
||||
"region": "Закарпатська область",
|
||||
"short_region": "Зак",
|
||||
"id": 3158,
|
||||
"value": 1859,
|
||||
"lat": 48.4,
|
||||
"lon": 23
|
||||
},
|
||||
{
|
||||
"region": "Чернівецька область",
|
||||
"short_region": "Чнц",
|
||||
"id": 3138,
|
||||
"value": 1376,
|
||||
"lat": 48.2915,
|
||||
"lon": 25.9403
|
||||
},
|
||||
{
|
||||
"region": "Київська область",
|
||||
"short_region": "К.о",
|
||||
"id": 3146,
|
||||
"value": 4848,
|
||||
"lat": 49.92,
|
||||
"lon": 30.57
|
||||
},
|
||||
{
|
||||
"region": "Харківська область",
|
||||
"short_region": "Хар",
|
||||
"id": 3143,
|
||||
"value": 4148,
|
||||
"lat": 49.5935,
|
||||
"lon": 36.5304
|
||||
},
|
||||
{
|
||||
"region": "Черкаська область",
|
||||
"short_region": "Чрк",
|
||||
"id": 3136,
|
||||
"value": 3001,
|
||||
"lat": 49.2,
|
||||
"lon": 31.4
|
||||
},
|
||||
{
|
||||
"region": "Дніпропетровська область",
|
||||
"short_region": "Дні",
|
||||
"id": 3140,
|
||||
"value": 7076,
|
||||
"lat": 48.4647,
|
||||
"lon": 35.0462
|
||||
},
|
||||
{
|
||||
"region": "Сумська область",
|
||||
"short_region": "Сум",
|
||||
"id": 3156,
|
||||
"value": 1670,
|
||||
"lat": 50.8077,
|
||||
"lon": 34.4981
|
||||
},
|
||||
{
|
||||
"region": "Полтавська область",
|
||||
"short_region": "Пол",
|
||||
"id": 3153,
|
||||
"value": 3065,
|
||||
"lat": 49.5883,
|
||||
"lon": 34.0514
|
||||
},
|
||||
{
|
||||
"region": "Запорізька область",
|
||||
"short_region": "Зап",
|
||||
"id": 3161,
|
||||
"value": 2205,
|
||||
"lat": 47.1388,
|
||||
"lon": 35.5396
|
||||
},
|
||||
{
|
||||
"region": "Херсонська область",
|
||||
"short_region": "Хер",
|
||||
"id": 3144,
|
||||
"value": 323,
|
||||
"lat": 46.6354,
|
||||
"lon": 33.5169
|
||||
},
|
||||
{
|
||||
"region": "Вінницька область",
|
||||
"short_region": "Він",
|
||||
"id": 3159,
|
||||
"value": 3362,
|
||||
"lat": 49.0331,
|
||||
"lon": 28.6682
|
||||
},
|
||||
{
|
||||
"region": "Житомирська область",
|
||||
"short_region": "Жит",
|
||||
"id": 3162,
|
||||
"value": 2717,
|
||||
"lat": 50.2649,
|
||||
"lon": 28.6767
|
||||
},
|
||||
{
|
||||
"region": "Хмельницька область",
|
||||
"short_region": "Хме",
|
||||
"id": 3145,
|
||||
"value": 2925,
|
||||
"lat": 49.4228,
|
||||
"lon": 26.9871
|
||||
},
|
||||
{
|
||||
"region": "Одеська область",
|
||||
"short_region": "Оде",
|
||||
"id": 3152,
|
||||
"value": 4896,
|
||||
"lat": 46.9825,
|
||||
"lon": 30.3233
|
||||
},
|
||||
{
|
||||
"region": "Кіровоградська область",
|
||||
"short_region": "Кір",
|
||||
"id": 3148,
|
||||
"value": 1801,
|
||||
"lat": 48.5079,
|
||||
"lon": 32.2623
|
||||
},
|
||||
{
|
||||
"region": "м.Севастополь",
|
||||
"short_region": "Сев",
|
||||
"id": 3155,
|
||||
"value": 0,
|
||||
"lat": 44.58,
|
||||
"lon": 33.58
|
||||
},
|
||||
{
|
||||
"region": "Чернігівська область",
|
||||
"short_region": "Чнг",
|
||||
"id": 3137,
|
||||
"value": 1776,
|
||||
"lat": 51.2982,
|
||||
"lon": 31.8893
|
||||
},
|
||||
{
|
||||
"region": "Донецька область",
|
||||
"short_region": "Дон",
|
||||
"id": 3141,
|
||||
"value": 933,
|
||||
"lat": 48.0159,
|
||||
"lon": 37.8028
|
||||
},
|
||||
{
|
||||
"region": "Миколаївська область",
|
||||
"short_region": "Мик",
|
||||
"id": 3151,
|
||||
"value": 2459,
|
||||
"lat": 47.275,
|
||||
"lon": 31.9946
|
||||
},
|
||||
{
|
||||
"region": "Луганська область",
|
||||
"short_region": "Луг",
|
||||
"id": 3149,
|
||||
"value": 0,
|
||||
"lat": 48.974,
|
||||
"lon": 39.0078
|
||||
},
|
||||
{
|
||||
"region": "Автономна Республіка Крим",
|
||||
"short_region": "АРК",
|
||||
"id": 3139,
|
||||
"value": 0,
|
||||
"lat": 45.3657,
|
||||
"lon": 34.4708
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
54
src/charts/histogram-original.vl.json
Normal file
54
src/charts/histogram-original.vl.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Trip Distance and Customers",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"data": {
|
||||
"url": "data/histogram.csv"
|
||||
},
|
||||
"mark": {
|
||||
"type": "bar",
|
||||
"fill": "#3182bd",
|
||||
"tooltip": true
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Trip_Distance",
|
||||
"type": "quantitative",
|
||||
"bin": {
|
||||
"step": 10
|
||||
},
|
||||
"axis": {
|
||||
"title": "Distance (in Km)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": false
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"aggregate": "count",
|
||||
"axis": {
|
||||
"title": "Number of Customers",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"axis": {
|
||||
"grid": true,
|
||||
"gridColor": "#ddd",
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
},
|
||||
"bar": {
|
||||
"binSpacing": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
54
src/charts/histogram-ukrainian.vl.json
Normal file
54
src/charts/histogram-ukrainian.vl.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Відстань поїздки та клієнти",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"data": {
|
||||
"url": "data/histogram.csv"
|
||||
},
|
||||
"mark": {
|
||||
"type": "bar",
|
||||
"fill": "#3182bd",
|
||||
"tooltip": true
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Trip_Distance",
|
||||
"type": "quantitative",
|
||||
"bin": {
|
||||
"step": 10
|
||||
},
|
||||
"axis": {
|
||||
"title": "Відстань (км)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": false
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"aggregate": "count",
|
||||
"axis": {
|
||||
"title": "Кількість клієнтів",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"axis": {
|
||||
"grid": true,
|
||||
"gridColor": "#ddd",
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
},
|
||||
"bar": {
|
||||
"binSpacing": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/charts/linechart-original.vl.json
Normal file
35
src/charts/linechart-original.vl.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"width": 600,
|
||||
"height": 400,
|
||||
"title": "Oil Prices",
|
||||
"data": {
|
||||
"url": "data/linechart.json"
|
||||
},
|
||||
"mark": {
|
||||
"type": "line",
|
||||
"point": true
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "date",
|
||||
"type": "temporal",
|
||||
"title": "Month",
|
||||
"axis": {
|
||||
"format": "%b %Y",
|
||||
"labelOverlap": false,
|
||||
"labelAngle": -25,
|
||||
"labelAlign": "right",
|
||||
"tickCount": "month"
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"title": "Oil Price (USD)",
|
||||
"scale": {
|
||||
"zero": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/charts/linechart-ukrainian.vl.json
Normal file
35
src/charts/linechart-ukrainian.vl.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"width": 600,
|
||||
"height": 400,
|
||||
"title": "Ціни на нафту",
|
||||
"data": {
|
||||
"url": "data/linechart.json"
|
||||
},
|
||||
"mark": {
|
||||
"type": "line",
|
||||
"point": true
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "date",
|
||||
"type": "temporal",
|
||||
"title": "Місяць",
|
||||
"axis": {
|
||||
"format": "%b %Y",
|
||||
"labelOverlap": false,
|
||||
"labelAngle": -25,
|
||||
"labelAlign": "right",
|
||||
"tickCount": "month"
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"title": "Ціна за барель нафти ($)",
|
||||
"scale": {
|
||||
"zero": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
src/charts/piechart-original.vl.json
Normal file
39
src/charts/piechart-original.vl.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Global Smartphone Market Share in 2021",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"config": {
|
||||
"legend": {
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12,
|
||||
"titleFontWeight": "bold"
|
||||
}
|
||||
},
|
||||
"width": 500, "height": 300,
|
||||
"data": {
|
||||
"values": [
|
||||
{"brand": "Samsung", "share": 25},
|
||||
{"brand": "Xiaomi", "share": 16},
|
||||
{"brand": "Apple", "share": 15},
|
||||
{"brand": "Oppo", "share": 10},
|
||||
{"brand": "Vivo", "share": 10},
|
||||
{"brand": "Others", "share": 24}
|
||||
]
|
||||
},
|
||||
"encoding": {
|
||||
"theta": {"field": "share", "type": "quantitative", "stack": true},
|
||||
"color": {"field": "brand", "type": "nominal", "legend": null}
|
||||
},
|
||||
"layer": [{
|
||||
"mark": {"type": "arc", "outerRadius": 120}
|
||||
}, {
|
||||
"mark": {"type": "text", "radius": 90},
|
||||
"encoding": {
|
||||
"text": {"field": "brand", "type": "nominal"},
|
||||
"color": {"value": "black"}
|
||||
}
|
||||
}]
|
||||
}
|
||||
39
src/charts/piechart-ukrainian.vl.json
Normal file
39
src/charts/piechart-ukrainian.vl.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Розподіл світового ринку смартфонів у 2021 році",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"config": {
|
||||
"legend": {
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12,
|
||||
"titleFontWeight": "bold"
|
||||
}
|
||||
},
|
||||
"width": 500, "height": 300,
|
||||
"data": {
|
||||
"values": [
|
||||
{"brand": "Samsung", "share": 25},
|
||||
{"brand": "Xiaomi", "share": 16},
|
||||
{"brand": "Apple", "share": 15},
|
||||
{"brand": "Oppo", "share": 10},
|
||||
{"brand": "Vivo", "share": 10},
|
||||
{"brand": "Інші", "share": 24}
|
||||
]
|
||||
},
|
||||
"encoding": {
|
||||
"theta": {"field": "share", "type": "quantitative", "stack": true},
|
||||
"color": {"field": "brand", "type": "nominal", "legend": null}
|
||||
},
|
||||
"layer": [{
|
||||
"mark": {"type": "arc", "outerRadius": 120}
|
||||
}, {
|
||||
"mark": {"type": "text", "radius": 90},
|
||||
"encoding": {
|
||||
"text": {"field": "brand", "type": "nominal"},
|
||||
"color": {"value": "black"}
|
||||
}
|
||||
}]
|
||||
}
|
||||
64
src/charts/scatterplot-original.vl.json
Normal file
64
src/charts/scatterplot-original.vl.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Weight and Height of 85 Individuals",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 400,
|
||||
"height": 400,
|
||||
"data": {
|
||||
"url": "data/scatterplot.csv"
|
||||
},
|
||||
"mark": {
|
||||
"type": "circle",
|
||||
"size": 40,
|
||||
"fill": "#3182bd",
|
||||
"opacity": 1
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Height",
|
||||
"type": "quantitative",
|
||||
"scale": {
|
||||
"domain": [155, 190]
|
||||
},
|
||||
"axis": {
|
||||
"title": "Height (cm)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true,
|
||||
"gridDash": [1, 1],
|
||||
"ticks": 5
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "Weight",
|
||||
"type": "quantitative",
|
||||
"scale": {
|
||||
"domain": [40, 75]
|
||||
},
|
||||
"axis": {
|
||||
"title": "Weight (kg)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true,
|
||||
"gridDash": [1, 1],
|
||||
"ticks": 8
|
||||
}
|
||||
},
|
||||
"tooltip": [
|
||||
{"field": "Height", "title": "Height", "format": ".1f"},
|
||||
{"field": "Weight", "title": "Weight", "format": ".1f"}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridOpacity": 0.5,
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
64
src/charts/scatterplot-ukrainian.vl.json
Normal file
64
src/charts/scatterplot-ukrainian.vl.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Вага та зріст 85 осіб",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 400,
|
||||
"height": 400,
|
||||
"data": {
|
||||
"url": "data/scatterplot.csv"
|
||||
},
|
||||
"mark": {
|
||||
"type": "circle",
|
||||
"size": 40,
|
||||
"fill": "#3182bd",
|
||||
"opacity": 1
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Height",
|
||||
"type": "quantitative",
|
||||
"scale": {
|
||||
"domain": [155, 190]
|
||||
},
|
||||
"axis": {
|
||||
"title": "Зріст (см)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true,
|
||||
"gridDash": [1, 1],
|
||||
"ticks": 5
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "Weight",
|
||||
"type": "quantitative",
|
||||
"scale": {
|
||||
"domain": [40, 75]
|
||||
},
|
||||
"axis": {
|
||||
"title": "Вага (кг)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true,
|
||||
"gridDash": [1, 1],
|
||||
"ticks": 8
|
||||
}
|
||||
},
|
||||
"tooltip": [
|
||||
{"field": "Height", "title": "Зріст", "format": ".1f"},
|
||||
{"field": "Weight", "title": "Вага", "format": ".1f"}
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridOpacity": 0.5,
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
82
src/charts/stacked100-original.vl.json
Normal file
82
src/charts/stacked100-original.vl.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Olympic Medal Distribution by Country",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"data": {
|
||||
"url": "data/stacked100.csv"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"encoding": {
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Percentage",
|
||||
"format": ".0%",
|
||||
"grid": true
|
||||
},
|
||||
"stack": "normalize"
|
||||
},
|
||||
"x": {
|
||||
"field": "Countries",
|
||||
"type": "nominal",
|
||||
"axis": {
|
||||
"title": null,
|
||||
"labelAngle": 40,
|
||||
"titleFontWeight": "bold"
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"field": "category",
|
||||
"type": "nominal",
|
||||
"scale": {
|
||||
"domain": [
|
||||
"Gold",
|
||||
"Silver",
|
||||
"Bronze"
|
||||
],
|
||||
"range": [
|
||||
"#FFD700",
|
||||
"#C0C0C0",
|
||||
"#CD7F32"
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
"title": "Medals",
|
||||
"orient": "right"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mark": "bar",
|
||||
"transform": [
|
||||
{
|
||||
"fold": [
|
||||
"Gold",
|
||||
"Silver",
|
||||
"Bronze"
|
||||
],
|
||||
"as": [
|
||||
"category",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"sort": [
|
||||
{"field": "category", "order": "descending"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"grid": true,
|
||||
"gridColor": "#ddd"
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/charts/stacked100-ukrainian.vl.json
Normal file
86
src/charts/stacked100-ukrainian.vl.json
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Розподіл олімпійських медалей за країною",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"data": {
|
||||
"url": "data/stacked100.csv"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"encoding": {
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Відсоток",
|
||||
"format": ".0%",
|
||||
"grid": true
|
||||
},
|
||||
"stack": "normalize"
|
||||
},
|
||||
"x": {
|
||||
"field": "CountriesUK",
|
||||
"type": "nominal",
|
||||
"axis": {
|
||||
"title": null,
|
||||
"labelAngle": 40,
|
||||
"titleFontWeight": "bold"
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"field": "category",
|
||||
"type": "nominal",
|
||||
"scale": {
|
||||
"domain": [
|
||||
"Золото",
|
||||
"Срібло",
|
||||
"Бронза"
|
||||
],
|
||||
"range": [
|
||||
"#FFD700",
|
||||
"#C0C0C0",
|
||||
"#CD7F32"
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
"title": "Медалі",
|
||||
"orient": "right"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mark": "bar",
|
||||
"transform": [
|
||||
{
|
||||
"fold": [
|
||||
"Gold",
|
||||
"Silver",
|
||||
"Bronze"
|
||||
],
|
||||
"as": [
|
||||
"category",
|
||||
"value"
|
||||
]
|
||||
},
|
||||
{
|
||||
"calculate": "datum.category === 'Gold' ? 'Золото' : datum.category === 'Silver' ? 'Срібло' : 'Бронза'",
|
||||
"as": "category"
|
||||
},
|
||||
{
|
||||
"sort": [
|
||||
{"field": "category", "order": "descending"}
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"grid": true,
|
||||
"gridColor": "#ddd"
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
122
src/charts/stackedareachart-original.vl.json
Normal file
122
src/charts/stackedareachart-original.vl.json
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Popular Girls' names in the UK",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 400,
|
||||
"height": 400,
|
||||
"data": {
|
||||
"values": [
|
||||
{
|
||||
"Year": 2009,
|
||||
"Amelia": 3625,
|
||||
"Isla": 1908,
|
||||
"Olivia": 5201
|
||||
},
|
||||
{
|
||||
"Year": 2010,
|
||||
"Amelia": 4227,
|
||||
"Isla": 2384,
|
||||
"Olivia": 5279
|
||||
},
|
||||
{
|
||||
"Year": 2011,
|
||||
"Amelia": 5054,
|
||||
"Isla": 2849,
|
||||
"Olivia": 4938
|
||||
},
|
||||
{
|
||||
"Year": 2012,
|
||||
"Amelia": 7061,
|
||||
"Isla": 3501,
|
||||
"Olivia": 4585
|
||||
},
|
||||
{
|
||||
"Year": 2013,
|
||||
"Amelia": 5570,
|
||||
"Isla": 3526,
|
||||
"Olivia": 4598
|
||||
},
|
||||
{
|
||||
"Year": 2014,
|
||||
"Amelia": 5327,
|
||||
"Isla": 4012,
|
||||
"Olivia": 4724
|
||||
}
|
||||
]
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Year",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Year",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Number of Girls",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"field": "name",
|
||||
"type": "nominal",
|
||||
"scale": {
|
||||
"domain": [
|
||||
"Amelia",
|
||||
"Isla",
|
||||
"Olivia"
|
||||
],
|
||||
"range": [
|
||||
"#3182bd",
|
||||
"#9ecae1",
|
||||
"#deebf7"
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
"title": null,
|
||||
"orient": "right"
|
||||
}
|
||||
}
|
||||
},
|
||||
"layer": [
|
||||
{
|
||||
"mark": {
|
||||
"type": "area",
|
||||
"opacity": 0.7
|
||||
},
|
||||
"transform": [
|
||||
{
|
||||
"fold": [
|
||||
"Amelia",
|
||||
"Isla",
|
||||
"Olivia"
|
||||
],
|
||||
"as": [
|
||||
"name",
|
||||
"value"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridOpacity": 0.5,
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
122
src/charts/stackedareachart-ukrainian.vl.json
Normal file
122
src/charts/stackedareachart-ukrainian.vl.json
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Популярність виробництва сортів меду",
|
||||
"fontSize": 16,
|
||||
"fontWeight": "bold"
|
||||
},
|
||||
"width": 400,
|
||||
"height": 400,
|
||||
"data": {
|
||||
"values": [
|
||||
{
|
||||
"Year": 2009,
|
||||
"Липовий": 3625,
|
||||
"Гречаний": 1908,
|
||||
"Акацієвий": 5201
|
||||
},
|
||||
{
|
||||
"Year": 2010,
|
||||
"Липовий": 4227,
|
||||
"Гречаний": 2384,
|
||||
"Акацієвий": 5279
|
||||
},
|
||||
{
|
||||
"Year": 2011,
|
||||
"Липовий": 5054,
|
||||
"Гречаний": 2849,
|
||||
"Акацієвий": 4938
|
||||
},
|
||||
{
|
||||
"Year": 2012,
|
||||
"Липовий": 7061,
|
||||
"Гречаний": 3501,
|
||||
"Акацієвий": 4585
|
||||
},
|
||||
{
|
||||
"Year": 2013,
|
||||
"Липовий": 5570,
|
||||
"Гречаний": 3526,
|
||||
"Акацієвий": 4598
|
||||
},
|
||||
{
|
||||
"Year": 2014,
|
||||
"Липовий": 5327,
|
||||
"Гречаний": 4012,
|
||||
"Акацієвий": 4724
|
||||
}
|
||||
]
|
||||
},
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "Year",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Рік",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Кількість тонн",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"field": "name",
|
||||
"type": "nominal",
|
||||
"scale": {
|
||||
"domain": [
|
||||
"Липовий",
|
||||
"Гречаний",
|
||||
"Акацієвий"
|
||||
],
|
||||
"range": [
|
||||
"#3182bd",
|
||||
"#9ecae1",
|
||||
"#deebf7"
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
"title": null,
|
||||
"orient": "right"
|
||||
}
|
||||
}
|
||||
},
|
||||
"layer": [
|
||||
{
|
||||
"mark": {
|
||||
"type": "area",
|
||||
"opacity": 0.7
|
||||
},
|
||||
"transform": [
|
||||
{
|
||||
"fold": [
|
||||
"Липовий",
|
||||
"Гречаний",
|
||||
"Акацієвий"
|
||||
],
|
||||
"as": [
|
||||
"name",
|
||||
"value"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"gridColor": "#ddd",
|
||||
"gridOpacity": 0.5,
|
||||
"labelFontSize": 11,
|
||||
"titleFontSize": 12
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/charts/stackedbarchart-original.vl.json
Normal file
86
src/charts/stackedbarchart-original.vl.json
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Room Service Prices"
|
||||
},
|
||||
"data": {
|
||||
"url": "data/stackedbarchart.csv"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "City",
|
||||
"type": "nominal",
|
||||
"axis": {
|
||||
"title": "Cities",
|
||||
"labelAngle": 40,
|
||||
"titleFontWeight": "bold"
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Cost ($)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
},
|
||||
"scale": {
|
||||
"domain": [
|
||||
0,
|
||||
70
|
||||
]
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"field": "category",
|
||||
"type": "nominal",
|
||||
"scale": {
|
||||
"domain": [
|
||||
"Sandwich",
|
||||
"Water",
|
||||
"Peanut",
|
||||
"Soda",
|
||||
"Vodka"
|
||||
],
|
||||
"range": [
|
||||
"#7fc97f",
|
||||
"#beaed4",
|
||||
"#fdc086",
|
||||
"#fb9a99",
|
||||
"#386cb0"
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
"title": null,
|
||||
"orient": "right"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mark": "bar",
|
||||
"transform": [
|
||||
{
|
||||
"fold": [
|
||||
"Sandwich",
|
||||
"Water",
|
||||
"Peanut",
|
||||
"Soda",
|
||||
"Vodka"
|
||||
],
|
||||
"as": [
|
||||
"category",
|
||||
"value"
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"grid": true,
|
||||
"gridColor": "#ddd"
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
87
src/charts/stackedbarchart-ukrainian.vl.json
Normal file
87
src/charts/stackedbarchart-ukrainian.vl.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
|
||||
"title": {
|
||||
"text": "Ціни на обслуговування в номері"
|
||||
},
|
||||
"data": {
|
||||
"url": "data/stackedbarchart.csv"
|
||||
},
|
||||
"width": 500,
|
||||
"height": 300,
|
||||
"encoding": {
|
||||
"x": {
|
||||
"field": "CityUK",
|
||||
"type": "nominal",
|
||||
"axis": {
|
||||
"title": "Місто",
|
||||
"labelAngle": 40,
|
||||
"titleFontWeight": "bold"
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"field": "value",
|
||||
"type": "quantitative",
|
||||
"axis": {
|
||||
"title": "Ціна ($)",
|
||||
"titleFontWeight": "bold",
|
||||
"grid": true
|
||||
},
|
||||
"scale": {
|
||||
"domain": [
|
||||
0,
|
||||
70
|
||||
]
|
||||
}
|
||||
},
|
||||
"color": {
|
||||
"field": "category",
|
||||
"type": "nominal",
|
||||
"scale": {
|
||||
"domain": [
|
||||
"Sandwich",
|
||||
"Water",
|
||||
"Peanut",
|
||||
"Soda",
|
||||
"Vodka"
|
||||
],
|
||||
"range": [
|
||||
"#7fc97f",
|
||||
"#beaed4",
|
||||
"#fdc086",
|
||||
"#fb9a99",
|
||||
"#386cb0"
|
||||
]
|
||||
},
|
||||
"legend": {
|
||||
"title": null,
|
||||
"orient": "right",
|
||||
"labelExpr": "datum.label == 'Sandwich' ? 'Сендвіч' : datum.label == 'Water' ? 'Вода' : datum.label == 'Peanut' ? 'Арахіс' : datum.label == 'Soda' ? 'Газована вода' : 'Горілка'"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mark": "bar",
|
||||
"transform": [
|
||||
{
|
||||
"fold": [
|
||||
"Sandwich",
|
||||
"Water",
|
||||
"Peanut",
|
||||
"Soda",
|
||||
"Vodka"
|
||||
],
|
||||
"as": [
|
||||
"category",
|
||||
"value"
|
||||
]
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"axis": {
|
||||
"grid": true,
|
||||
"gridColor": "#ddd"
|
||||
},
|
||||
"view": {
|
||||
"stroke": null
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/charts/treemap-original.vl.json
Normal file
38
src/charts/treemap-original.vl.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega/v5.json",
|
||||
"width": 500,
|
||||
"height": 500,
|
||||
"marks": [
|
||||
{
|
||||
"type": "image",
|
||||
"encode": {
|
||||
"enter": {
|
||||
"url": {
|
||||
"value": "data/treemap-uk.png"
|
||||
},
|
||||
"x": {
|
||||
"value": 0
|
||||
},
|
||||
"y": {
|
||||
"value": 0
|
||||
},
|
||||
"width": {
|
||||
"value": 500
|
||||
},
|
||||
"height": {
|
||||
"value": 500
|
||||
},
|
||||
"aspect": {
|
||||
"value": true
|
||||
},
|
||||
"align": {
|
||||
"value": "left"
|
||||
},
|
||||
"baseline": {
|
||||
"value": "top"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
38
src/charts/treemap-ukrainian.vl.json
Normal file
38
src/charts/treemap-ukrainian.vl.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"$schema": "https://vega.github.io/schema/vega/v5.json",
|
||||
"width": 500,
|
||||
"height": 500,
|
||||
"marks": [
|
||||
{
|
||||
"type": "image",
|
||||
"encode": {
|
||||
"enter": {
|
||||
"url": {
|
||||
"value": "data/treemap-uk.png"
|
||||
},
|
||||
"x": {
|
||||
"value": 0
|
||||
},
|
||||
"y": {
|
||||
"value": 0
|
||||
},
|
||||
"width": {
|
||||
"value": 500
|
||||
},
|
||||
"height": {
|
||||
"value": 500
|
||||
},
|
||||
"aspect": {
|
||||
"value": true
|
||||
},
|
||||
"align": {
|
||||
"value": "left"
|
||||
},
|
||||
"baseline": {
|
||||
"value": "top"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
130
src/css/styles.css
Normal file
130
src/css/styles.css
Normal file
@@ -0,0 +1,130 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #5cb85c;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #4cae4c;
|
||||
}
|
||||
|
||||
.quiz-question {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.questionnaire {
|
||||
display: none;
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.results {
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
form label {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
form input, form select, form textarea {
|
||||
margin-bottom: 15px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
form button {
|
||||
align-self: flex-start;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#quiz {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#chart {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#question-text, #options {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.option-button {
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
#options label {
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#submit {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: center;
|
||||
}
|
||||
15
src/data/barchart.csv
Normal file
15
src/data/barchart.csv
Normal file
@@ -0,0 +1,15 @@
|
||||
Country,Speed,Country_UK
|
||||
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
src/data/bubblechart.csv
Normal file
12
src/data/bubblechart.csv
Normal file
@@ -0,0 +1,12 @@
|
||||
City,Length,NumberofStations,Ridership,CityUK
|
||||
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
src/data/choropleth.csv
Normal file
52
src/data/choropleth.csv
Normal file
@@ -0,0 +1,52 @@
|
||||
state,rate,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
src/data/histogram.csv
Normal file
1374
src/data/histogram.csv
Normal file
File diff suppressed because it is too large
Load Diff
50
src/data/linechart.json
Normal file
50
src/data/linechart.json
Normal file
@@ -0,0 +1,50 @@
|
||||
[
|
||||
{
|
||||
"date": "2020-01-01",
|
||||
"value": 57.52
|
||||
},
|
||||
{
|
||||
"date": "2020-02-01",
|
||||
"value": 50.54
|
||||
},
|
||||
{
|
||||
"date": "2020-03-01",
|
||||
"value": 29.21
|
||||
},
|
||||
{
|
||||
"date": "2020-04-01",
|
||||
"value": 16.55
|
||||
},
|
||||
{
|
||||
"date": "2020-05-01",
|
||||
"value": 28.56
|
||||
},
|
||||
{
|
||||
"date": "2020-06-01",
|
||||
"value": 38.31
|
||||
},
|
||||
{
|
||||
"date": "2020-07-01",
|
||||
"value": 40.71
|
||||
},
|
||||
{
|
||||
"date": "2020-08-01",
|
||||
"value": 42.34
|
||||
},
|
||||
{
|
||||
"date": "2020-09-01",
|
||||
"value": 39.63
|
||||
},
|
||||
{
|
||||
"date": "2020-10-01",
|
||||
"value": 39.40
|
||||
},
|
||||
{
|
||||
"date": "2020-11-01",
|
||||
"value": 40.94
|
||||
},
|
||||
{
|
||||
"date": "2020-12-01",
|
||||
"value": 47.02
|
||||
}
|
||||
]
|
||||
7
src/data/piechart.csv
Normal file
7
src/data/piechart.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
Brand,Share
|
||||
Samsung,25
|
||||
Xiaomi,16
|
||||
Apple,15
|
||||
Oppo,10
|
||||
Vivo,10
|
||||
Others,24
|
||||
|
312
src/data/questions.json
Normal file
312
src/data/questions.json
Normal file
@@ -0,0 +1,312 @@
|
||||
{
|
||||
"quizzes": {
|
||||
"original": {
|
||||
"questions": [
|
||||
{
|
||||
"chart": "linechart",
|
||||
"chart_uk": "лінійний графік",
|
||||
"question": "What was the price of a barrel of oil in February 2020?",
|
||||
"options": [
|
||||
"$50.54",
|
||||
"$47.02",
|
||||
"$42.34",
|
||||
"$42.34",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "$50.54"
|
||||
},
|
||||
{
|
||||
"chart": "barchart",
|
||||
"chart_uk": "стовпчаста діаграма",
|
||||
"question": "What is the average internet speed in Japan?",
|
||||
"options": [
|
||||
"42.30 Mbps",
|
||||
"40.51 Mbps",
|
||||
"35.25 Mbps",
|
||||
"16.16 Mbps",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "40.51 Mbps"
|
||||
},
|
||||
{
|
||||
"chart": "stackedbarchart",
|
||||
"chart_uk": "накопичувана стовпчаста діаграма",
|
||||
"question": "What is the cost of peanuts in Seoul?",
|
||||
"options": [
|
||||
"$6.1",
|
||||
"$5.2",
|
||||
"$7.5",
|
||||
"$4.5",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "$6.1"
|
||||
},
|
||||
{
|
||||
"chart": "stacked100",
|
||||
"chart_uk": "накопичувана стовпчаста діаграма 100%",
|
||||
"question": "Which country has the lowest proportion of Gold medals?",
|
||||
"options": [
|
||||
"Great Britain",
|
||||
"U.S.A.",
|
||||
"Japan",
|
||||
"Australia",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "Great Britain"
|
||||
},
|
||||
{
|
||||
"chart": "piechart",
|
||||
"chart_uk": "кругова діаграма",
|
||||
"question": "What is the approximate global smartphone market share of Samsung?",
|
||||
"options": [
|
||||
"17.6%",
|
||||
"25.3%",
|
||||
"10.9%",
|
||||
"35.2%",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "17.6%"
|
||||
},
|
||||
{
|
||||
"chart": "histogram",
|
||||
"chart_uk": "гістограма",
|
||||
"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"
|
||||
],
|
||||
"answer": "30 - 40 Km"
|
||||
},
|
||||
{
|
||||
"chart": "scatterplot",
|
||||
"chart_uk": "точкова діаграма",
|
||||
"question": "There is a negative linear relationship between the height and the weight of the 85 males.",
|
||||
"options": [
|
||||
"True",
|
||||
"False",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "False"
|
||||
},
|
||||
{
|
||||
"chart": "areachart",
|
||||
"chart_uk": "площева діаграма",
|
||||
"question": "What was the average price of a pound of coffee beans in October 2019?",
|
||||
"options": [
|
||||
"$0.71",
|
||||
"$0.90",
|
||||
"$0.80",
|
||||
"$0.63",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "$0.71"
|
||||
},
|
||||
{
|
||||
"chart": "stackedareachart",
|
||||
"chart_uk": "накопичувана площева діаграма",
|
||||
"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"
|
||||
],
|
||||
"answer": "1 to 2"
|
||||
},
|
||||
{
|
||||
"chart": "bubblechart",
|
||||
"chart_uk": "бульбашкова діаграма",
|
||||
"question": "Which city's metro system has the largest number of stations?",
|
||||
"options": [
|
||||
"Beijing",
|
||||
"Shanghai",
|
||||
"London",
|
||||
"Seoul",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "Shanghai"
|
||||
},
|
||||
{
|
||||
"chart": "choropleth",
|
||||
"chart_uk": "хороплетна карта",
|
||||
"question": "In 2020, the unemployment rate for Washington (WA) was higher than that of Wisconsin (WI).",
|
||||
"options": [
|
||||
"True",
|
||||
"False",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "True"
|
||||
},
|
||||
{
|
||||
"chart": "treemap",
|
||||
"chart_uk": "деревоподібна діаграма",
|
||||
"question": "eBay is nested in the Software category.",
|
||||
"options": [
|
||||
"True",
|
||||
"False",
|
||||
"Skip"
|
||||
],
|
||||
"answer": "False"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ukrainian": {
|
||||
"questions": [
|
||||
{
|
||||
"chart": "linechart",
|
||||
"chart_uk": "лінійний графік",
|
||||
"question": "Яка була ціна за барель нафти у лютому 2020 року?",
|
||||
"options": [
|
||||
"$50.54",
|
||||
"$47.02",
|
||||
"$42.34",
|
||||
"$42.34",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "$50.54"
|
||||
},
|
||||
{
|
||||
"chart": "barchart",
|
||||
"chart_uk": "стовпчаста діаграма",
|
||||
"question": "Яка середня швидкість інтернету в Японії?",
|
||||
"options": [
|
||||
"42.30 Мбіт/с",
|
||||
"40.51 Мбіт/с",
|
||||
"35.25 Мбіт/с",
|
||||
"16.16 Мбіт/с",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "40.51 Мбіт/с"
|
||||
},
|
||||
{
|
||||
"chart": "stackedbarchart",
|
||||
"chart_uk": "накопичувана стовпчаста діаграма",
|
||||
"question": "Яка вартість арахісу в Сеулі?",
|
||||
"options": [
|
||||
"$6.1",
|
||||
"$5.2",
|
||||
"$7.5",
|
||||
"$4.5",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "$6.1"
|
||||
},
|
||||
{
|
||||
"chart": "stacked100",
|
||||
"chart_uk": "накопичувана стовпчаста діаграма 100%",
|
||||
"question": "Яка країна має найменшу частку золотих медалей?",
|
||||
"options": [
|
||||
"Велика Британія",
|
||||
"США",
|
||||
"Японія",
|
||||
"Австралія",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "Велика Британія"
|
||||
},
|
||||
{
|
||||
"chart": "piechart",
|
||||
"chart_uk": "кругова діаграма",
|
||||
"question": "Яка приблизна глобальна частка ринку смартфонів Samsung?",
|
||||
"options": [
|
||||
"17.6%",
|
||||
"25.3%",
|
||||
"10.9%",
|
||||
"35.2%",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "17.6%"
|
||||
},
|
||||
{
|
||||
"chart": "histogram",
|
||||
"chart_uk": "гістограма",
|
||||
"question": "Яку відстань клієнти найчастіше подорожували на таксі?",
|
||||
"options": [
|
||||
"60 - 70 км",
|
||||
"30 - 40 км",
|
||||
"20 - 30 км",
|
||||
"50 - 60 км",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "30 - 40 км"
|
||||
},
|
||||
{
|
||||
"chart": "scatterplot",
|
||||
"chart_uk": "точкова діаграма",
|
||||
"question": "Існує негативний лінійний зв'язок між зростом та вагою 85 чоловіків.",
|
||||
"options": [
|
||||
"Правда",
|
||||
"Неправда",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "Неправда"
|
||||
},
|
||||
{
|
||||
"chart": "areachart",
|
||||
"chart_uk": "площева діаграма",
|
||||
"question": "Яка була середня ціна фунта кавових зерен у жовтні 2019 року?",
|
||||
"options": [
|
||||
"$0.71",
|
||||
"$0.90",
|
||||
"$0.80",
|
||||
"$0.63",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "$0.71"
|
||||
},
|
||||
{
|
||||
"chart": "stackedareachart",
|
||||
"chart_uk": "накопичувана площева діаграма",
|
||||
"question": "Яке було співвідношення гречаного меду до липового у 2012 році?",
|
||||
"options": [
|
||||
"1 до 1",
|
||||
"1 до 2",
|
||||
"1 до 3",
|
||||
"1 до 4",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "1 до 2"
|
||||
},
|
||||
{
|
||||
"chart": "bubblechart",
|
||||
"chart_uk": "бульбашкова діаграма",
|
||||
"question": "Метро якого міста має найбільшу кількість станцій?",
|
||||
"options": [
|
||||
"Пекін",
|
||||
"Шанхай",
|
||||
"Лондон",
|
||||
"Сеул",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "Шанхай"
|
||||
},
|
||||
{
|
||||
"chart": "choropleth",
|
||||
"chart_uk": "хороплетна карта",
|
||||
"question": "У першому півріччі 2024 р. кількість шлюбів в Харківській області була більшою, ніж у Волинській області.",
|
||||
"options": [
|
||||
"Правда",
|
||||
"Неправда",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "Правда"
|
||||
},
|
||||
{
|
||||
"chart": "treemap",
|
||||
"chart_uk": "деревоподібна діаграма",
|
||||
"question": "eBay вкладено в категорію \"програмне забезпечення\".",
|
||||
"options": [
|
||||
"Правда",
|
||||
"Неправда",
|
||||
"Пропустити"
|
||||
],
|
||||
"answer": "Неправда"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/data/scatterplot.csv
Normal file
86
src/data/scatterplot.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
|
||||
|
5
src/data/stacked100.csv
Normal file
5
src/data/stacked100.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
Countries,CountriesUK,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
|
||||
|
11
src/data/stackedbarchart.csv
Normal file
11
src/data/stackedbarchart.csv
Normal file
@@ -0,0 +1,11 @@
|
||||
City,CityUK,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
|
||||
|
53
src/data/state-coordinates.json
Normal file
53
src/data/state-coordinates.json
Normal file
@@ -0,0 +1,53 @@
|
||||
[
|
||||
{ "code": "NE", "latitude": 41.5, "longitude": -99.68 },
|
||||
{ "code": "SD", "latitude": 44.5, "longitude": -100.23 },
|
||||
{ "code": "UT", "latitude": 39.32, "longitude": -111.09 },
|
||||
{ "code": "ND", "latitude": 47.5, "longitude": -100.47 },
|
||||
{ "code": "IA", "latitude": 42.07, "longitude": -93.5 },
|
||||
{ "code": "ID", "latitude": 44.24, "longitude": -114.47 },
|
||||
{ "code": "ME", "latitude": 45.37, "longitude": -69.24 },
|
||||
{ "code": "VT", "latitude": 44.07, "longitude": -72.67 },
|
||||
{ "code": "WY", "latitude": 43.07, "longitude": -107.29 },
|
||||
{ "code": "AL", "latitude": 32.8, "longitude": -86.79 },
|
||||
{ "code": "KS", "latitude": 38.5, "longitude": -98.38 },
|
||||
{ "code": "MT", "latitude": 46.92, "longitude": -110.45 },
|
||||
{ "code": "AR", "latitude": 34.75, "longitude": -92.29 },
|
||||
{ "code": "MO", "latitude": 38.57, "longitude": -92.6 },
|
||||
{ "code": "OK", "latitude": 35.47, "longitude": -97.52 },
|
||||
{ "code": "MN", "latitude": 46.39, "longitude": -94.64 },
|
||||
{ "code": "SC", "latitude": 33.84, "longitude": -81.16 },
|
||||
{ "code": "VA", "latitude": 37.77, "longitude": -78.17 },
|
||||
{ "code": "WI", "latitude": 44.5, "longitude": -89.5 },
|
||||
{ "code": "GA", "latitude": 32.64, "longitude": -83.44 },
|
||||
{ "code": "KY", "latitude": 37.53, "longitude": -85.3 },
|
||||
{ "code": "NH", "latitude": 43.68, "longitude": -71.58 },
|
||||
{ "code": "MD", "latitude": 39.05, "longitude": -76.64 },
|
||||
{ "code": "IN", "latitude": 40.27, "longitude": -86.13 },
|
||||
{ "code": "CO", "latitude": 39.11, "longitude": -105.36 },
|
||||
{ "code": "NC", "latitude": 35.78, "longitude": -80.79 },
|
||||
{ "code": "TN", "latitude": 35.86, "longitude": -86.66 },
|
||||
{ "code": "OR", "latitude": 43.93, "longitude": -120.55 },
|
||||
{ "code": "TX", "latitude": 31.47, "longitude": -99.33 },
|
||||
{ "code": "FL", "latitude": 27.99, "longitude": -81.76 },
|
||||
{ "code": "AK", "latitude": 64.2, "longitude": -149.49 },
|
||||
{ "code": "DE", "latitude": 38.99, "longitude": -75.51 },
|
||||
{ "code": "AZ", "latitude": 34.05, "longitude": -111.09 },
|
||||
{ "code": "CT", "latitude": 41.6, "longitude": -72.76 },
|
||||
{ "code": "DC", "latitude": 38.91, "longitude": -77.01 },
|
||||
{ "code": "MS", "latitude": 32.74, "longitude": -89.67 },
|
||||
{ "code": "OH", "latitude": 40.19, "longitude": -82.67 },
|
||||
{ "code": "LA", "latitude": 30.98, "longitude": -91.96 },
|
||||
{ "code": "WV", "latitude": 38.64, "longitude": -80.62 },
|
||||
{ "code": "NM", "latitude": 34.52, "longitude": -106.1 },
|
||||
{ "code": "WA", "latitude": 47.39, "longitude": -121.49 },
|
||||
{ "code": "MA", "latitude": 42.24, "longitude": -71.53 },
|
||||
{ "code": "PA", "latitude": 40.88, "longitude": -77.79 },
|
||||
{ "code": "RI", "latitude": 41.68, "longitude": -71.51 },
|
||||
{ "code": "IL", "latitude": 40.34, "longitude": -89.0 },
|
||||
{ "code": "NJ", "latitude": 40.14, "longitude": -74.67 },
|
||||
{ "code": "MI", "latitude": 44.18, "longitude": -84.51 },
|
||||
{ "code": "NY", "latitude": 42.95, "longitude": -75.53 },
|
||||
{ "code": "CA", "latitude": 37.25, "longitude": -119.61 },
|
||||
{ "code": "HI", "latitude": 20.79, "longitude": -156.33 },
|
||||
{ "code": "NV", "latitude": 38.5, "longitude": -117.02 }
|
||||
]
|
||||
51502
src/data/topo-USA.json
Normal file
51502
src/data/topo-USA.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/data/treemap-en.png
Normal file
BIN
src/data/treemap-en.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
BIN
src/data/treemap-uk.png
Normal file
BIN
src/data/treemap-uk.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
55
src/js/app.js
Normal file
55
src/js/app.js
Normal file
@@ -0,0 +1,55 @@
|
||||
// src/js/app.js
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const currentPage = window.location.pathname.split('/').pop();
|
||||
|
||||
if (currentPage === 'consent.html') {
|
||||
initConsentPage();
|
||||
} else if (currentPage === 'quiz.html') {
|
||||
initQuizPage();
|
||||
} else if (currentPage === 'questionnaire.html') {
|
||||
initQuestionnairePage();
|
||||
} else if (currentPage === 'results.html') {
|
||||
initResultsPage();
|
||||
}
|
||||
});
|
||||
|
||||
function initConsentPage() {
|
||||
const consentButton = document.getElementById('consent-button');
|
||||
consentButton.addEventListener('click', function() {
|
||||
fetch('../data/questions.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const quizVersions = Object.keys(data.quizzes);
|
||||
const randomVersion = quizVersions[Math.floor(Math.random() * quizVersions.length)];
|
||||
localStorage.setItem('quizVersion', randomVersion);
|
||||
window.location.href = 'quiz.html';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initQuizPage() {
|
||||
const version = localStorage.getItem('quizVersion');
|
||||
loadQuestions(version);
|
||||
}
|
||||
|
||||
function initQuestionnairePage() {
|
||||
// Logic for initializing the questionnaire page
|
||||
}
|
||||
|
||||
function initResultsPage() {
|
||||
// Logic for displaying results
|
||||
}
|
||||
|
||||
function loadQuestions(version) {
|
||||
fetch('../data/questions.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const questions = data.quizzes[version];
|
||||
displayQuestions(questions);
|
||||
});
|
||||
}
|
||||
|
||||
function displayQuestions(questions) {
|
||||
// Logic to display questions on the quiz page
|
||||
}
|
||||
14
src/js/consent.js
Normal file
14
src/js/consent.js
Normal file
@@ -0,0 +1,14 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const consentButton = document.getElementById('consentButton');
|
||||
|
||||
consentButton.addEventListener('click', function() {
|
||||
fetch('../data/questions.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const quizVersions = Object.keys(data.quizzes);
|
||||
const randomVersion = quizVersions[Math.floor(Math.random() * quizVersions.length)];
|
||||
localStorage.setItem('quizVersion', randomVersion);
|
||||
window.location.href = 'quiz.html';
|
||||
});
|
||||
});
|
||||
});
|
||||
79
src/js/questionnaire.js
Normal file
79
src/js/questionnaire.js
Normal file
@@ -0,0 +1,79 @@
|
||||
// This file handles the logic for the questionnaire, including collecting additional participant information after the quiz.
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const questionnaireForm = document.getElementById('questionnaire-form');
|
||||
|
||||
questionnaireForm.addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Form validation
|
||||
const age = document.getElementById('age').value;
|
||||
if (age < 0 || age > 120) {
|
||||
showError('Please enter a valid age between 0 and 120');
|
||||
return;
|
||||
}
|
||||
|
||||
const participantData = {
|
||||
age: age,
|
||||
gender: document.getElementById('gender').value,
|
||||
education: document.getElementById('education').value,
|
||||
colorBlind: document.getElementById('color-blind').value,
|
||||
familiarity: document.getElementById('familiarity').value,
|
||||
englishLevel: document.getElementById('english-level').value,
|
||||
ukrainianLevel: document.getElementById('ukrainian-level').value,
|
||||
visualizationDifficulty: document.getElementById('visualization-difficulty').value,
|
||||
quizDifficulty: document.getElementById('quiz-difficulty').value,
|
||||
kseAffiliation: document.getElementById('kse-affiliation').value,
|
||||
comments: document.getElementById('comments').value
|
||||
};
|
||||
|
||||
// Disable form while submitting
|
||||
const submitButton = document.querySelector('button[type="submit"]');
|
||||
submitButton.disabled = true;
|
||||
|
||||
// Store participant data in local storage
|
||||
localStorage.setItem('participantData', JSON.stringify(participantData));
|
||||
|
||||
// Retrieve existing quiz data
|
||||
const allQuizzes = JSON.parse(localStorage.getItem('allQuizzes') || '{}');
|
||||
const quizId = 'quiz';
|
||||
if (allQuizzes[quizId]) {
|
||||
allQuizzes[quizId].participantData = participantData;
|
||||
localStorage.setItem('allQuizzes', JSON.stringify(allQuizzes));
|
||||
}
|
||||
|
||||
// Send data to the backend
|
||||
fetch('/api/responses', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(allQuizzes)
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
console.log('Success:', data);
|
||||
window.location.href = 'results.html';
|
||||
} else {
|
||||
throw new Error(data.message || 'Failed to submit the form');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error:', error);
|
||||
showError('Failed to submit the form. Please try again.');
|
||||
submitButton.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
function showError(message) {
|
||||
const errorDiv = document.getElementById('error-message');
|
||||
errorDiv.textContent = message;
|
||||
errorDiv.style.display = 'block';
|
||||
}
|
||||
});
|
||||
199
src/js/quiz.js
Normal file
199
src/js/quiz.js
Normal file
@@ -0,0 +1,199 @@
|
||||
// This file manages the quiz functionality, including loading questions from the JSON file, displaying them to the user, and collecting answers.
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const quizContainer = document.getElementById('quiz');
|
||||
const resultsContainer = document.getElementById('results');
|
||||
const timerDisplay = document.getElementById('time');
|
||||
const version = localStorage.getItem('quizVersion');
|
||||
const quizId = 'quiz';
|
||||
let questions = [];
|
||||
let currentQuestionIndex = 0;
|
||||
let score = 0;
|
||||
let quizResults = [];
|
||||
let timeLeft = 25;
|
||||
let timer;
|
||||
let startTime = new Date().toISOString();
|
||||
|
||||
// Generate and store browser ID
|
||||
function generateBrowserId() {
|
||||
return 'xxxx-xxxx-4xxx-yxxx-xxxx-xxxx-xxxx-xxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
const browserId = localStorage.getItem('browserId') || generateBrowserId();
|
||||
localStorage.setItem('browserId', browserId);
|
||||
|
||||
const browserInfo = {
|
||||
userAgent: navigator.userAgent,
|
||||
screenResolution: `${window.screen.width}x${window.screen.height}`,
|
||||
operatingSystem: navigator.platform
|
||||
};
|
||||
|
||||
// Check if there is a completed quiz
|
||||
const allQuizzes = JSON.parse(localStorage.getItem('allQuizzes') || '{}');
|
||||
if (allQuizzes[quizId] && allQuizzes[quizId].completed) {
|
||||
alert("You have already completed the quiz. Redirecting to the questionnaire.");
|
||||
window.location.href = 'index.html';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('data/questions.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (!data.quizzes || !data.quizzes[version] || !data.quizzes[version].questions) {
|
||||
throw new Error('Invalid quiz data or version');
|
||||
}
|
||||
questions = data.quizzes[version].questions;
|
||||
displayQuestion();
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading quiz:', error);
|
||||
quizContainer.innerHTML = '<p>Error loading quiz. Please try again later.</p>';
|
||||
});
|
||||
|
||||
function displayQuestion() {
|
||||
if (!questions || currentQuestionIndex >= questions.length) {
|
||||
showResults();
|
||||
return;
|
||||
}
|
||||
|
||||
// Complete timer reset
|
||||
stopTimer();
|
||||
timeLeft = 25;
|
||||
timerDisplay.textContent = timeLeft;
|
||||
|
||||
const question = questions[currentQuestionIndex];
|
||||
const chartFile = `charts/${question.chart}-${version}.vl.json`;
|
||||
|
||||
// Embed the Vega-Lite chart
|
||||
const embedOptions = {
|
||||
actions: false, // Disable kebab menu
|
||||
tooltip: false // Disable tooltips
|
||||
};
|
||||
|
||||
if (version === 'ukrainian') {
|
||||
embedOptions.timeFormatLocale = {
|
||||
dateTime: "%A, %e %B %Y р. %X",
|
||||
date: "%d.%m.%Y",
|
||||
time: "%H:%M:%S",
|
||||
periods: ["", ""],
|
||||
days: ["неділя", "понеділок", "вівторок", "середа", "четвер", "п'ятниця", "субота"],
|
||||
shortDays: ["нд", "пн", "вт", "ср", "чт", "пт", "сб"],
|
||||
months: ["січень", "лютий", "березень", "квітень", "травень", "червень", "липень", "серпень", "вересень", "жовтень", "листопад", "грудень"],
|
||||
shortMonths: ["січ", "лют", "бер", "кві", "тра", "чер", "лип", "сер", "вер", "жов", "лис", "гру"]
|
||||
};
|
||||
}
|
||||
|
||||
vegaEmbed('#chart', chartFile, embedOptions).catch(console.error);
|
||||
|
||||
// Update question and options
|
||||
document.getElementById('question-text').innerHTML = question.question;
|
||||
document.getElementById('options').innerHTML = question.options.map((option, index) => `
|
||||
<button class="option-button" data-value="${option}">${option}</button>
|
||||
`).join('');
|
||||
|
||||
// Start fresh timer
|
||||
startTimer();
|
||||
|
||||
// Add event listeners to option buttons
|
||||
document.querySelectorAll('.option-button').forEach(button => {
|
||||
button.addEventListener('click', () => submitAnswer(button.dataset.value));
|
||||
});
|
||||
}
|
||||
|
||||
function stopTimer() {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
// Clear any existing timer
|
||||
stopTimer();
|
||||
|
||||
// Ensure display shows starting value
|
||||
timerDisplay.textContent = timeLeft;
|
||||
|
||||
timer = setInterval(() => {
|
||||
timeLeft--;
|
||||
timerDisplay.textContent = timeLeft;
|
||||
|
||||
if (timeLeft <= 0) {
|
||||
stopTimer();
|
||||
alert("Time's up! Moving to the next question.");
|
||||
submitAnswer(true);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function storeQuizProgress() {
|
||||
const currentProgress = {
|
||||
quizId: quizId,
|
||||
version: version,
|
||||
score: score,
|
||||
currentQuestionIndex: currentQuestionIndex,
|
||||
totalQuestions: questions.length,
|
||||
answers: quizResults,
|
||||
lastUpdated: new Date().toISOString(),
|
||||
participantData: JSON.parse(localStorage.getItem('participantData') || '{}'),
|
||||
startTime: startTime, // Store start time
|
||||
browserId: browserId, // Store browser ID
|
||||
browserInfo: browserInfo // Store browser info
|
||||
};
|
||||
const allQuizzes = JSON.parse(localStorage.getItem('allQuizzes') || '{}');
|
||||
allQuizzes[quizId] = currentProgress;
|
||||
localStorage.setItem('allQuizzes', JSON.stringify(allQuizzes));
|
||||
}
|
||||
|
||||
function submitAnswer(selectedAnswer = null) {
|
||||
// Stop the timer first
|
||||
stopTimer();
|
||||
|
||||
if (!selectedAnswer) {
|
||||
alert('Please select an answer before proceeding.');
|
||||
startTimer(); // Restart timer if no answer selected
|
||||
return;
|
||||
}
|
||||
|
||||
const currentQuestion = questions[currentQuestionIndex];
|
||||
const isCorrect = selectedAnswer === currentQuestion.answer;
|
||||
if (isCorrect) {
|
||||
score++;
|
||||
}
|
||||
|
||||
// Store the question result
|
||||
quizResults.push({
|
||||
question: currentQuestion.question,
|
||||
selectedAnswer: selectedAnswer,
|
||||
correctAnswer: currentQuestion.answer,
|
||||
isCorrect: isCorrect,
|
||||
questionIndex: currentQuestionIndex,
|
||||
timestamp: new Date().toISOString(),
|
||||
timeSpent: 25 - timeLeft,
|
||||
chartType: currentQuestion.chart,
|
||||
chartTypeUk: currentQuestion.chart_uk // Include chart_uk type
|
||||
});
|
||||
|
||||
// Store progress after each answer
|
||||
storeQuizProgress();
|
||||
|
||||
currentQuestionIndex++;
|
||||
// Reset timer state before showing next question
|
||||
timeLeft = 25;
|
||||
displayQuestion();
|
||||
}
|
||||
|
||||
function showResults() {
|
||||
// Mark quiz as completed
|
||||
const allQuizzes = JSON.parse(localStorage.getItem('allQuizzes') || '{}');
|
||||
allQuizzes[quizId].completed = true;
|
||||
allQuizzes[quizId].completedAt = new Date().toISOString();
|
||||
localStorage.setItem('allQuizzes', JSON.stringify(allQuizzes));
|
||||
|
||||
// Redirect to the questionnaire page
|
||||
window.location.href = 'questionnaire.html';
|
||||
}
|
||||
});
|
||||
30
src/js/results.js
Normal file
30
src/js/results.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const resultsContainer = document.getElementById('results');
|
||||
const resultsHeader = document.getElementById('results-header');
|
||||
const resultsTableBody = document.getElementById('results-table-body');
|
||||
|
||||
const allQuizzes = JSON.parse(localStorage.getItem('allQuizzes') || '{}');
|
||||
const quizData = allQuizzes['quiz'];
|
||||
|
||||
function displayResults() {
|
||||
const totalQuestions = quizData.totalQuestions;
|
||||
const correctAnswers = quizData.score;
|
||||
const percentage = ((correctAnswers / totalQuestions) * 100).toFixed(2);
|
||||
|
||||
resultsHeader.textContent = `Результати тесту: ${correctAnswers}/${totalQuestions}, ${percentage}%`;
|
||||
|
||||
let resultsHTML = '';
|
||||
|
||||
quizData.answers.forEach(answer => {
|
||||
resultsHTML += `
|
||||
<tr>
|
||||
<td>${answer.question}</td>
|
||||
<td>${answer.chartTypeUk}</td>
|
||||
<td>${answer.isCorrect ? '✅' : '❌'}</td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
|
||||
resultsTableBody.innerHTML = resultsHTML;
|
||||
}
|
||||
|
||||
window.onload = displayResults;
|
||||
Reference in New Issue
Block a user