diff --git a/Quiz-001-Basic-for-Webversion.txt b/Quiz-001-Basic-for-Webversion.txt new file mode 100644 index 0000000..5259afd --- /dev/null +++ b/Quiz-001-Basic-for-Webversion.txt @@ -0,0 +1,167 @@ +What is particulate matter (PM) 2.5? +-- all PM under 2.5 mm radius +-- all PM under 2.5 micro-m radius +-- all PM under 2.5 mm diameter +-- all PM under 2.5 micro-m diameter + +AQI standards for +-- Air Quality Information +-- Air Quality Index +-- Air Quality Inventory +-- Air Quality Impacts + +PM2.5 is a +-- Primary pollutant +-- Secondary pollutant +-- Has both primary and secondary pollutants +-- Don't know + +Global climate Change is same as air pollution we experience in the city's +-- True +-- False +-- Sometimes +-- Don't know + +SMOG is +-- Suspended-PM and Fog +-- Smoke and Fog +-- Sulfur Dioxide and Fog +-- Soot and Fog + +Air quality is same as Air Quality Index (AQI) +-- True +-- False +-- Sometimes +-- Don't know + +Which pollutant is responsible for acid rain? +-- Ammonia +-- Carbon Monoxide +-- Ozone +-- Sulfur Dioxide + +Which of the following is not a necessary ingredient in the production of Ozone? +-- Carbon Dioxide +-- Nitrogen Oxides +-- Sunlight +-- Volatile Organic Compounds + +What is the unit of Air Quality Index (AQI)? +-- micro-gm/m3 +-- none +-- percentage (%) +-- tons/year + +What is a typical unit of emissions? +-- kg/day +-- tons/year +-- It depends +-- A & B + +What is a typical unit of pollution? +-- micro-gm/m3 +-- tons/year +-- It depends +-- A & B + +Pollutant that gets attached to blood (haemoglobin) and leads to premature mortality? +-- Carbon Dioxide +-- Carbon Monoxide +-- Nitrogen Dioxide +-- Ozone + +Good ozone protecting us from UV radiation, resides in? +-- Biosphere +-- Mesosphere +-- Stratosphere +-- Troposphere + +Bad ozone that we don't want to breathe, resides in? +-- Biosphere +-- Mesosphere +-- Stratosphere +-- Troposphere + +Chronic Obstructive Pulmonary Disorder (COPD) due to air pollution is associated with this organ +-- Blood +-- Heart +-- Lungs +-- Eyes + +Cardiac arrests due to air pollution is associated with this organ +-- Blood +-- Heart +-- Lungs +-- Eyes + +Ambient air pollution sources are? +-- Everything that burns +-- It depends on when and where +-- Mostly biomass burning +-- Mostly transport + +Air quality index (AQI) provides more information than air quality data +-- True +-- False +-- Sometimes +-- Don't know + +Air quality index information is preferred for regulatory purposes +-- True +-- False +-- Sometimes +-- Don't know + +Air quality index information is preferred for public awareness +-- True +-- False +-- Sometimes +-- Don't know + +Air quality index value is same as PM2.5 concentration value +-- True +-- False +-- Sometimes +-- Don't know + +Discussions on emissions is same as discussions on pollution +-- True +-- False +-- Sometimes +-- Don't know + +Regulatory-grade monitoring systems do not require any maintenance +-- True +-- False +-- Sometimes +-- Don't know + +All monitoring systems require regular maintenance and calibration +-- True +-- False +-- Sometimes +-- Don't know + +Satellite observations are superior to ground measurements +-- True +-- False +-- Sometimes +-- Don't know + +Best way to reduce pollution +-- Increase the number of monitoring stations +-- Control emissions at all the sources +-- Use vacuum cleaner like equipment to suck pollution in the air +-- All the above + +Air Quality Index (AQI) methodology is same for all the countries +-- True +-- False +-- Sometimes +-- Don't know + +Monitoring data is enough to know everything about air pollution +-- True +-- False +-- Sometimes +-- Don't know \ No newline at end of file diff --git a/README.md b/README.md index 1360b48..fafe254 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,31 @@ # Multiple Choice Quiz (ReactJS) -Screen Shot 2022-01-19 at 6 19 13 PM +Answer the quiz on: [AirQualityQuiz](https://urbanemissionsinfo.github.io/airqualityquiz/) + +The slide doc to this app can be found here: [Slides](https://docs.google.com/presentation/d/1Q-Ula2IBLRKel3bROX5Ly3UaF7uEDVBFx6Wfe9IGZ7U/edit?usp=sharing) + +![alt text](image.png) + +## Deploy on GH pages +[Video tutorial](https://www.youtube.com/watch?v=7wzuievFjrk) -Screen Shot 2022-01-19 at 6 19 32 PM ## Improvements ### Easy 🟢 -- **Visual updates**: Animations, Sounds, Font Styling, Background, Colors, etc. -- Store list of questions in a seperate file - `questions.txt` -- Change list of questions to something else - -### Medium 🟡 -- After game reset, **scramble order of questions** randomly -- After clicking an option, pause for 2 sec, show correct answer, then move onto next one -- At the end show list of wrong questions with the correct answers -- Create different ReactJS components - -### Hard 🔴 -- Create a **live leaderboard** of users using a backend (Firebase, AWS, etc.) +- [ ]**Visual updates**: Animations, Sounds, Font Styling, Background, Colors, etc. +- [x] Store list of questions in a seperate file - `questions.csv` +- [x] Place `questions.csv` on Google Sheets and serve it from there // add 'Loading quiz' for lag. +- [x] Add multiple quiz urls served by multiple GoogleSheets +- [x] Create a #users tracker + +### Medium 🟡 + +- [x] After game reset, **scramble order of questions** randomly +- [x] After clicking an option, show correct answer, then move onto next one (button or pause for 5 seconds) +- [ ] At the end show list of wrong questions with the correct answers +- [ ] Create different ReactJS components + +### Hard 🔴 - requires backend. +- [x] Collect scores - total and questionwise. +- [ ] Create a **live leaderboard** of users diff --git a/image.png b/image.png new file mode 100644 index 0000000..a970ab1 Binary files /dev/null and b/image.png differ diff --git a/package-lock.json b/package-lock.json index 49fed82..0ddfb43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,22 @@ { - "name": "multiple-choice-quiz", + "name": "air-quality-quiz", "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "multiple-choice-quiz", + "name": "air-quality-quiz", "version": "0.1.0", "dependencies": { "@testing-library/jest-dom": "^5.16.1", "@testing-library/react": "^12.1.2", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.9", + "gh-pages": "^6.3.0", + "moment": "^2.30.1", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-router-dom": "^6.29.0", "react-scripts": "5.0.0", "web-vitals": "^2.1.3" } @@ -2669,6 +2673,15 @@ "node": ">= 8" } }, + "node_modules/@remix-run/router": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.22.0.tgz", + "integrity": "sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz", @@ -4277,6 +4290,31 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/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==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -6087,6 +6125,12 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.49.tgz", "integrity": "sha512-k/0t1TRfonHIp8TJKfjBu2cKj8MqYTiEpOhci+q7CVEE5xnCQnx1pTa+V8b/sdhe4S3PR4p4iceEQWhGrKQORQ==" }, + "node_modules/email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", + "license": "MIT" + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -7182,6 +7226,32 @@ "minimatch": "^3.0.4" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -7280,15 +7350,16 @@ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==" }, "node_modules/follow-redirects": { - "version": "1.14.7", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", - "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -7609,6 +7680,57 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gh-pages": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz", + "integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==", + "license": "MIT", + "dependencies": { + "async": "^3.2.4", + "commander": "^13.0.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^11.1.1", + "globby": "^11.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/gh-pages/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/gh-pages/node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -10855,6 +10977,15 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -12658,6 +12789,12 @@ "node": ">= 0.10" } }, + "node_modules/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==", + "license": "MIT" + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -12954,6 +13091,38 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.29.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.29.0.tgz", + "integrity": "sha512-DXZJoE0q+KyeVw75Ck6GkPxFak63C4fGqZGNijnWgzB/HzSP1ZfTlBj5COaGWwhrMQ/R8bXiq5Ooy4KG+ReyjQ==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.22.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.29.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.29.0.tgz", + "integrity": "sha512-pkEbJPATRJ2iotK+wUwHfy0xs2T59YPEN8BQxVCPeBZvK7kfPESRc/nyxzdcxR17hXgUPYx2whMwl+eo9cUdnQ==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.22.0", + "react-router": "6.29.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.0.tgz", @@ -14064,6 +14233,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -14573,6 +14754,18 @@ "node": ">=8" } }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -17625,6 +17818,11 @@ } } }, + "@remix-run/router": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.22.0.tgz", + "integrity": "sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw==" + }, "@rollup/plugin-babel": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz", @@ -18815,6 +19013,28 @@ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz", "integrity": "sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==" }, + "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" + }, + "dependencies": { + "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" + } + } + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -20170,6 +20390,11 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.49.tgz", "integrity": "sha512-k/0t1TRfonHIp8TJKfjBu2cKj8MqYTiEpOhci+q7CVEE5xnCQnx1pTa+V8b/sdhe4S3PR4p4iceEQWhGrKQORQ==" }, + "email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==" + }, "emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -20972,6 +21197,21 @@ "minimatch": "^3.0.4" } }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==" + }, + "filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, "filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -21048,9 +21288,9 @@ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==" }, "follow-redirects": { - "version": "1.14.7", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", - "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, "fork-ts-checker-webpack-plugin": { "version": "6.5.0", @@ -21260,6 +21500,42 @@ "get-intrinsic": "^1.1.1" } }, + "gh-pages": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz", + "integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==", + "requires": { + "async": "^3.2.4", + "commander": "^13.0.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^11.1.1", + "globby": "^11.1.0" + }, + "dependencies": { + "async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==" + }, + "fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -23601,6 +23877,11 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -24792,6 +25073,11 @@ } } }, + "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==" + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -25002,6 +25288,23 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-router": { + "version": "6.29.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.29.0.tgz", + "integrity": "sha512-DXZJoE0q+KyeVw75Ck6GkPxFak63C4fGqZGNijnWgzB/HzSP1ZfTlBj5COaGWwhrMQ/R8bXiq5Ooy4KG+ReyjQ==", + "requires": { + "@remix-run/router": "1.22.0" + } + }, + "react-router-dom": { + "version": "6.29.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.29.0.tgz", + "integrity": "sha512-pkEbJPATRJ2iotK+wUwHfy0xs2T59YPEN8BQxVCPeBZvK7kfPESRc/nyxzdcxR17hXgUPYx2whMwl+eo9cUdnQ==", + "requires": { + "@remix-run/router": "1.22.0", + "react-router": "6.29.0" + } + }, "react-scripts": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.0.tgz", @@ -25832,6 +26135,14 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -26193,6 +26504,14 @@ "punycode": "^2.1.1" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", diff --git a/package.json b/package.json index 433f0ee..935c20e 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,25 @@ { - "name": "multiple-choice-quiz", + "homepage": "https://urbanemissionsinfo.github.io/airqualityquiz", + "name": "air-quality-quiz", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "^5.16.1", "@testing-library/react": "^12.1.2", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.9", + "gh-pages": "^6.3.0", + "moment": "^2.30.1", "react": "^17.0.2", "react-dom": "^17.0.2", + "react-router-dom": "^6.29.0", "react-scripts": "5.0.0", "web-vitals": "^2.1.3" }, "scripts": { "start": "react-scripts start", + "predeploy": "npm run build", + "deploy": "gh-pages -d build", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" diff --git a/public/index.html b/public/index.html index bbc4f82..69d15db 100644 --- a/public/index.html +++ b/public/index.html @@ -6,13 +6,15 @@ - Multiple Choice Quiz + Air Quality Quiz + +
diff --git a/src/App.css b/src/App.css index ce91dd4..cbbf85d 100644 --- a/src/App.css +++ b/src/App.css @@ -11,7 +11,7 @@ height: auto; /* Visual */ - background-color: gray; + background-color: rgb(23, 81,18); padding: 16px; border-radius: 16px; color: white; @@ -25,15 +25,16 @@ ul { li { margin-top: 8px; - background-color: darkgray; + background-color: rgba(255, 255, 255, 0.86); padding: 16px; - border: 3px solid white; + border: 3px solid rgb(0, 0, 0); border-radius: 20px; font-size: 20px; + color: black; } .question-text { - color: darkblue; + color: rgb(255, 255, 255); font-size: 24px; } @@ -58,7 +59,7 @@ li { } button { - background-color: red; /* Green */ + background-color: rgb(23, 81,18); border: none; color: white; padding: 16px 24px; @@ -67,6 +68,25 @@ button { display: inline-block; font-size: 16px; font-weight: bold; - border-radius: 24px; + margin-top: 8px; +} +.disabled { + pointer-events: none; /* Disable clicks */ + opacity: 0.6; /* Make it look disabled */ + cursor: default; /* Change cursor */ +} +.feedback { + /* Center the div */ + margin: 0 auto; + /* Dimensions */ + width: 70%; /* Can be in percentage also. */ + height: auto; + + /* Visual */ + background-color: rgb(212, 220, 154); + padding: 16px; + border-radius: 16px; + color: rgb(0, 0, 0); + margin-top: 10px; } diff --git a/src/App.js b/src/App.js index 5360555..83728e3 100644 --- a/src/App.js +++ b/src/App.js @@ -1,128 +1,241 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import "./App.css"; +import { HashRouter as Router, Routes, Route, Link} from 'react-router-dom'; // Import necessary components +import axios from 'axios'; -function App() { - // Properties - const [showResults, setShowResults] = useState(false); +// Helper function to convert CSV to questions (shared by both quizzes) +function csvToQuestions(csvString) { + const lines = csvString.trim().split("\n"); + const headers = lines[0].split(","); + const questions = []; + + for (let i = 1; i < lines.length; i++) { + const values = lines[i].split(","); + const questionId = values[0]; + const questionText = values[1]; + const obj = { a: 2, b: 3, c: 4, d: 5 }; + const correctAnswerIndex = obj[values[6].replace("\r", "")]; // Assuming 'correct_ans' is at index 6 + const options = []; + for (let j = 2; j <= 5; j++) { + options.push({ + id: j - 2, + text: values[j], + isCorrect: j === correctAnswerIndex, + }); + } + + questions.push({ + id: questionId, + text: questionText, + options: options, + answer_explanation: values[7] + }); + } + // Shuffle the questions array once (using Fisher-Yates algorithm) + for (let i = questions.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [questions[i], questions[j]] = [questions[j], questions[i]];} + const selected_questions = questions.slice(0,10); + return selected_questions; +} + +// QUIZ COMPONENT (reusable) +function Quiz({ googleSheetURL, quizTitle }) { + // State Variables + const [questions, setQuestions] = useState([]); const [currentQuestion, setCurrentQuestion] = useState(0); const [score, setScore] = useState(0); + const [showResults, setShowResults] = useState(false); + const [loading, setLoading] = useState(true); // ✅ New state to track loading + const [selectedOption, setSelectedOption] = useState(null); + const [feedback, setFeedback] = useState(null); + const [showNextButton, setShowNextButton] = useState(false); // New state for button visibility + const [responses, setResponses] = useState([]); // New state to store responses + const [qids, setQids] = useState([]); // New state to store question IDs - const questions = [ - { - text: "What is the capital of America?", - options: [ - { id: 0, text: "New York City", isCorrect: false }, - { id: 1, text: "Boston", isCorrect: false }, - { id: 2, text: "Santa Fe", isCorrect: false }, - { id: 3, text: "Washington DC", isCorrect: true }, - ], - }, - { - text: "What year was the Constitution of America written?", - options: [ - { id: 0, text: "1787", isCorrect: true }, - { id: 1, text: "1776", isCorrect: false }, - { id: 2, text: "1774", isCorrect: false }, - { id: 3, text: "1826", isCorrect: false }, - ], - }, - { - text: "Who was the second president of the US?", - options: [ - { id: 0, text: "John Adams", isCorrect: true }, - { id: 1, text: "Paul Revere", isCorrect: false }, - { id: 2, text: "Thomas Jefferson", isCorrect: false }, - { id: 3, text: "Benjamin Franklin", isCorrect: false }, - ], - }, - { - text: "What is the largest state in the US?", - options: [ - { id: 0, text: "California", isCorrect: false }, - { id: 1, text: "Alaska", isCorrect: true }, - { id: 2, text: "Texas", isCorrect: false }, - { id: 3, text: "Montana", isCorrect: false }, - ], - }, - { - text: "Which of the following countries DO NOT border the US?", - options: [ - { id: 0, text: "Canada", isCorrect: false }, - { id: 1, text: "Russia", isCorrect: true }, - { id: 2, text: "Cuba", isCorrect: true }, - { id: 3, text: "Mexico", isCorrect: false }, - ], - }, - ]; - - // Helper Functions - - /* A possible answer was clicked */ - const optionClicked = (isCorrect) => { - // Increment the score - if (isCorrect) { - setScore(score + 1); + + useEffect(() => { + loadQuestions(); + }, [googleSheetURL]); // Add googleSheetURL as a dependency + + const loadQuestions = () => { + setLoading(true); // ✅ Start loading + + fetch(googleSheetURL, { + headers: { "content-type": "text/csv;charset=UTF-8" }, + method: "GET", + }) + .then((response) => { + if (!response.ok) { + throw new Error("Network response was not ok"); + } + return response.text(); + }) + .then((csvData) => { + const data = csvToQuestions(csvData); + setQuestions(data); + setLoading(false); // ✅ Stop loading when questions are set + const question_ids = data.map(question => question.id); + setQids(() => question_ids); // Correct Way to Update State based on previous value. + }) + .catch((error) => { + console.error("Error fetching CSV file:", error); + setLoading(false); // ✅ Stop loading even if there is an error + + }) + }; + + useEffect(() => { + console.log("qids in useEffect:", qids); // Correct: Shows the updated array +}, [qids]); // This useEffect runs whenever qids changes + + // Function to change score and show feedback after option click + const optionClicked = (isCorrect, option) => { + // Save first option clicked + if (!selectedOption) { + responses.push(option.id); } + + if (isCorrect) { + if (!selectedOption) { // Only allow click if no option is selected yet + setScore(score + 1); + setFeedback("Correct :) !"); + } + } else {setFeedback("Incorrect :( ");} + + setSelectedOption(option); // This ensures that there is no change in responses, score and feedback when user clicks other options + console.log(responses); + setShowNextButton(true); // Show the "Next Question" button + }; + const goToNextQuestion = () => { if (currentQuestion + 1 < questions.length) { - setCurrentQuestion(currentQuestion + 1); + setCurrentQuestion(currentQuestion + 1); + setSelectedOption(null); + setFeedback(null); + setShowNextButton(false); // Hide the button } else { - setShowResults(true); + saveScore(); + setShowResults(true); + setFeedback(null); + setShowNextButton(false); } - }; +}; + +const saveScore = async () => { + console.log(qids); + try { + const scoreData = { + quizName: quizTitle, // The quiz title + score: score, // The user's score + date: new Date().toISOString(), // Current date and time in ISO 8601 format (important!) + question_ids: qids, + responses: responses, + }; + const response = await axios.post('https://airqualityquiz-backend.onrender.com/api/saveScore', scoreData); // Or your full URL if deployed + console.log('Score saved successfully:', response.data); // Log the response from the server + } catch (error) { + console.error('Error saving score:', error); // Display an error message to the user + if (error.response) { + // The request was made and the server responded with a status code that falls out of the range of 2xx + console.error("Response data:", error.response.data); + console.error("Response status:", error.response.status); + console.error("Response headers:", error.response.headers); + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of + // http.ClientRequest in node.js + console.error("Request:", error.request); + } else { + // Something happened in setting up the request that triggered an Error + console.error("Error message:", error.message); + } + } +}; - /* Resets the game back to default */ - const restartGame = () => { +const restartGame = () => { setScore(0); setCurrentQuestion(0); setShowResults(false); + loadQuestions(); // Reload questions to shuffle + }; return ( -
- {/* 1. Header */} -

USA Quiz 🇺🇸

- - {/* 2. Current Score */} -

Score: {score}

- - {/* 3. Show results or show the question game */} - {showResults ? ( - /* 4. Final Results */ -
-

Final Results

-

- {score} out of {questions.length} correct - ( - {(score / questions.length) * 100}%) -

- -
- ) : ( - /* 5. Question Card */ -
- {/* Current Question */} -

- Question: {currentQuestion + 1} out of {questions.length} -

-

{questions[currentQuestion].text}

- - {/* List of possible answers */} - -
+
{/* Add a class for styling */} +

{quizTitle}

{/* Display the quiz title */} +

Each quiz has 10 questions selected from a pool of questions. Participants are encouraged to take the test multiple times

+ {(loading) ? (

Loading quiz...

) : ( + <> {/* React fragment start */} +

Score: {score}

+ {showResults ? ( +
+

Final Results

+

+ {score} out of {questions.length} correct - ( + {(score / questions.length) * 100}%) +

+

+
{/* Link to Home */} +
+ ) : ( +
+

+ Question: {currentQuestion + 1} out of {questions.length} +

+

{questions[currentQuestion]?.text}

+
    + {questions[currentQuestion]?.options.map((option) => ( +
  • (optionClicked(option.isCorrect, option))}> + {option.text} +
  • + ))} +
+
+ )} + {/* Feedback */} + {feedback && ( +
+

{feedback}

+

Correct Answer: {questions[currentQuestion]?.options.find(opt => opt.isCorrect)?.text}

+

{questions[currentQuestion]?.answer_explanation}

+
+ )} + {/* Next Question Button */} + {showNextButton && ( // Show the button only when showNextButton is true + + )} + )}
); } -export default App; +// APP COMPONENT +function App() { + const GOOGLE_SHEET_CSV_URL_1 = "https://docs.google.com/spreadsheets/d/e/2PACX-1vSzzNg3HDQK3vUKpEnIwOREwa-SeRIcfYoECkL1qwivnChSUy5xrI7vE8Gpipuo_TxX6YDerL97rfGG/pub?gid=329704009&single=true&output=csv"; // URL for Quiz 1 + const GOOGLE_SHEET_CSV_URL_2 = "https://docs.google.com/spreadsheets/d/e/2PACX-1vSzzNg3HDQK3vUKpEnIwOREwa-SeRIcfYoECkL1qwivnChSUy5xrI7vE8Gpipuo_TxX6YDerL97rfGG/pub?gid=0&single=true&output=csv"; // URL for Quiz 2 + + return ( + +
+ + +

Air Quality Quizzes

+ Air Quality Basics Quiz
{/* Link to Basic Quiz */} + Air Quality Advanced Quiz (Coming soon...) {/* Link to Advanced Quiz */} +
+ } + /> + + } /> + {/* } /> */} + {/* Add more routes as needed */} + +
+ + ); +} + +export default App; \ No newline at end of file diff --git a/src/Appp.js b/src/Appp.js new file mode 100644 index 0000000..823a702 --- /dev/null +++ b/src/Appp.js @@ -0,0 +1,181 @@ +import React, { useEffect, useState } from "react"; +import "./App.css"; +import { HashRouter as Router, Routes, Route, Link} from 'react-router-dom'; // Import necessary components + +// Helper function to convert CSV to questions (shared by both quizzes) +function csvToQuestions(csvString) { + const lines = csvString.trim().split("\n"); + const headers = lines[0].split(","); + const questions = []; + for (let i = 1; i < lines.length; i++) { + const values = lines[i].split(","); + const questionId = parseInt(values[0], 10); + const questionText = values[1]; + const obj = { a: 2, b: 3, c: 4, d: 5 }; + const correctAnswerIndex = obj[values[6].replace("\r", "")]; // Assuming 'correct_ans' is at index 6 + + const options = []; + for (let j = 2; j <= 5; j++) { + options.push({ + id: j - 2, + text: values[j], + isCorrect: j === correctAnswerIndex, + }); + } + + questions.push({ + id: questionId, + text: questionText, + options: options, + }); + } + + // Shuffle the questions array once (using Fisher-Yates algorithm) + for (let i = questions.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [questions[i], questions[j]] = [questions[j], questions[i]]; + } + + const selected_questions = questions.slice(0,10); + const set = selected_questions.map(question => question.id); + + console.log(set); + + return selected_questions; +} + +// Quiz Component (reusable) +function Quiz({ googleSheetURL, quizTitle }) { + const [questions, setQuestions] = useState([]); + const [currentQuestion, setCurrentQuestion] = useState(0); + const [score, setScore] = useState(0); + const [showResults, setShowResults] = useState(false); + const [loading, setLoading] = useState(true); // ✅ New state to track loading + const [selectedOption, setSelectedOption] = useState(null); + const [feedback, setFeedback] = useState(null); + const [answerExplanation, setAnswerExplanation] = useState(null); // New state for explanation + + + + + useEffect(() => { + loadQuestions(); + }, [googleSheetURL]); // Add googleSheetURL as a dependency + + const loadQuestions = () => { + setLoading(true); // ✅ Start loading + + fetch(googleSheetURL, { + headers: { "content-type": "text/csv;charset=UTF-8" }, + method: "GET", + }) + .then((response) => { + if (!response.ok) { + throw new Error("Network response was not ok"); + } + return response.text(); + }) + .then((csvData) => { + const data = csvToQuestions(csvData); + setQuestions(data); + setLoading(false); // ✅ Stop loading when questions are set + + }) + .catch((error) => { + console.error("Error fetching CSV file:", error); + setLoading(false); // ✅ Stop loading even if there is an error + + }) + }; + + const optionClicked = (isCorrect) => { + if (isCorrect) { + setScore(score + 1); + } + + if (currentQuestion + 1 < questions.length) { + setCurrentQuestion(currentQuestion + 1); + } else { + setShowResults(true); + } + }; + + const restartGame = () => { + setScore(0); + setCurrentQuestion(0); + setShowResults(false); + loadQuestions(); // Reload questions to shuffle + + }; + + return ( +
{/* Add a class for styling */} +

{quizTitle}

{/* Display the quiz title */} +

Each quiz has 10 questions selected from a larger pool of questions. + Participants are encouraged to take the test multiple times

+ {(loading) ? ( +

Loading quiz...

+ ) : ( + <> +

Score: {score}

+ {showResults ? ( +
+

Final Results

+

+ {score} out of {questions.length} correct - ( + {(score / questions.length) * 100}%) +

+

+
{/* Link to Home */} +
+ + ) : ( +
+

+ Question: {currentQuestion + 1} out of {questions.length} +

+

{questions[currentQuestion]?.text}

+ +
+ + + )} + + )} +
+ ); +} + + +function App() { + const GOOGLE_SHEET_CSV_URL_1 = "https://docs.google.com/spreadsheets/d/e/2PACX-1vSzzNg3HDQK3vUKpEnIwOREwa-SeRIcfYoECkL1qwivnChSUy5xrI7vE8Gpipuo_TxX6YDerL97rfGG/pub?gid=0&single=true&output=csv"; // URL for Quiz 1 + const GOOGLE_SHEET_CSV_URL_2 = "https://docs.google.com/spreadsheets/d/e/2PACX-1vSzzNg3HDQK3vUKpEnIwOREwa-SeRIcfYoECkL1qwivnChSUy5xrI7vE8Gpipuo_TxX6YDerL97rfGG/pub?gid=329704009&single=true&output=csv"; // URL for Quiz 2 + + return ( + +
+ + +

Air Quality Quizzes

+ Air Quality Basic Quiz
{/* Link to Basic Quiz */} + Air Quality Advanced Quiz {/* Link to Advanced Quiz */} +
+ } /> + } /> + } /> + {/* Add more routes as needed */} + + +
+ ); + +} + +export default App; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 62adcf3..b7729e2 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,9 @@ import App from './App'; ReactDOM.render( + + , document.getElementById('root') ); diff --git a/src/quiz.csv b/src/quiz.csv new file mode 100644 index 0000000..3769371 --- /dev/null +++ b/src/quiz.csv @@ -0,0 +1,25 @@ +question_id,text,option_a,option_b,option_c,option_d,correct_ans +1,What is Particulate Matter (PM) 2.5?,All PM with radius less than 2.5 µm,All PM with radius less than 2.5 mm,All PM with diameter less than 2.5 µm,All PM with diameter less than 2.5 mm,c +2,Which gas is responsible for acid rain?,Ozone (O3),Carbon Dioxide (CO2),Carbon Monoxide (CO),Sulphur Dioxide (SO2),d +3,Which of the following is not a necessary ingredient in the production of 'Global' Tropospheric Ozone?,Nitrogen Oxides (NOx),Carbon dioxide (CO2),Volatile Organic Compounds (VOCs),Sunlight,b +4,Which of the following gaseous pollutants can directly contribute to aerosol concentrations?,Particulate Matter (PM 2.5),Sulphur Dioxide (SO2),Ozone (O3),Carbon Monoxide (CO),b +5,What is the unit of Air Quality Index (AQI) ?,Parts per million (ppm),Micrograms (µg),Micrograms per unit volume (µg/m3),None,d +6,What is the fundamental equation in building an Emissions Inventory?,Activity * Emissions Factor,Activity / Emissions Factor,Emissions Factor / Activity,Activity + Emissions Factor,a +7,What is the representative area of an air quality monitor?,Area with a radius of 1 km,Area with a radius of 2 km,Area with a radius of 4 km,Area with a radius of 10 km,b +8,What does source apportionment study aim to determine?,When the pollution occurred,The geographical location of pollution,What all activities contributed to the air pollution,The chemical composition of pollutants,c +9,What action is recommended when idling in traffic for more than 30 seconds?,"Keep the engine running to avoid restart, which causes more pollution",Reduce air conditioning,Turn off the engine,Put the vehicle on a Neutral gear,c +10,Main pollutant of volcanic eruptions is?,Nitrogen Dioxide (NO2),Sulphur Dioxide (SO2),Ozone (O3),Volatile Organic Compounds (VOCs),b +11,Pollutant that gets attached to blood (haemoglobin) and leads to premature mortality?,Nitrogen Dioxide (NO2),Benzene (C6H6),Ozone (O3),Carbon Monoxide (CO),d +12,Lightning produces this pollutant in large quantities?,Nitrogen oxides (NOx),Halogen compounds,Ozone (O3),Volatile Organic Compounds (VOCs),a +13,Pollutant concentrations most used for calculating health impacts?,Sulphur Dioxide (SO2) and Nitrogen Dioxide (NO2),Particulate Matter 2.5 (PM2.5) and Ozone (O3),Nitrogen Dioxide (NO2) and Particulate Matter 2.5 (PM2.5),"NO2, Benzene (C6H6) and Ozone (O3)",b +14,Good ozone protecting us from UV radiation resides in?,Troposphere,Heliosphere,Mesosphere,Stratosphere,d +15,Chronic Obstructive Pulmonary Disorder (COPD) is associated with?,Heart,Lungs,Eyes,Veins,b +16,Ultrafine particulates are Particulate Matter (PM) less than?,10μm,1μm,0.1μm,0.01μm,c +17,Ambient air pollution sources are?,Everything that burns,mostly power plants,mostly transport,waste burning,a +18,Which of the following statements is TRUE,Air quality index provides more information than air quality data,Air quality index information is preferred for regulatory purposes,Air quality index information is preferred for public awareness,Air quality index value is same as PM2.5 concentration value,c +19,Which of the following statements is TRUE,Discussions on pollution is same as discussions on concentrations,Discussions on emissions is same as discussions on pollution,Discussions on emissions is same as discussions on air quality index,Discussions on pollutants is same as discussions on air quality index,a +20,Which of the following statements is TRUE,Two monitoring stations is a good sample to represent a city,Low-cost sensors are same as regulatory-grade monitoring systems,Regulatory-grade systems do not require any maintenance,All monitoring systems require regular maintenance and calibration,d +21,Which of the following statements is TRUE,Satellite observations can directly replace ground measurements,Satellite observations are superior to ground measurements,Satellite observations are a proxy to ground measurements,Satellite observations are a proxy to emission inventories,c +22,What is TRUE about Aerosol Optical Depth (AOD)?,AOD is a proxy of PM2.5 or PM10 concentrations in the air,AOD from satellites is same as PM2.5/PM10 from ground measurements,AOD can be used for policy discussions globally,AOD from a single satellite pass per day is enough to deduce pollution,a +23,Best way to reduce pollution,Increase the number of monitoring stations,Control emissions at all the sources,Use vacuum cleaners to suck pollution in the air,All the above,b +24,Which of the following statements is TRUE about source apportionment techniques,Sampling-chemical-analysis approach is always preferred,Sampling-chemical-analysis approach is the best,Emissions-pollution-modelling approach is always preferred,Emissions-pollution-modelling approach has better spatial and temporal coverage,d \ No newline at end of file