├── .gitignore ├── LICENCE ├── README.md ├── readme ├── form_desktop.webp ├── form_mobile.webp ├── form_tablet.webp ├── header.webp ├── home_desktop.webp ├── home_mobile.webp ├── home_tablet.webp ├── play_classic_desktop.webp ├── play_classic_mobile.webp ├── play_classic_tablet.webp ├── play_time_desktop.webp ├── play_time_mobile.webp └── play_time_tablet.webp └── source_code ├── .env.example ├── .eslintrc.json ├── jsconfig.json ├── next.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── bg-gamemodes.svg ├── bg-home.svg ├── categories-icons │ ├── art.svg │ ├── entertainment.svg │ ├── general culture.svg │ ├── geography.svg │ ├── history.svg │ ├── science.svg │ ├── space.svg │ └── technology.svg ├── favicon.svg ├── letters │ ├── letter-a.svg │ ├── letter-b.svg │ ├── letter-c.svg │ └── letter-d.svg ├── play_bg.webp └── sounds │ ├── correct_answer.mp3 │ ├── pop-down.mp3 │ ├── pop-up-off.mp3 │ ├── pop-up-on.mp3 │ ├── pop.mp3 │ ├── switch-off.mp3 │ ├── switch-on.mp3 │ ├── win.mp3 │ └── wrong_answer.mp3 ├── src ├── assets │ ├── categories.json │ ├── fifty.svg │ ├── questions.json │ ├── sound-off.svg │ ├── sound-on.svg │ ├── star.svg │ └── trophy.svg ├── components │ ├── Form │ │ ├── JsxForm.jsx │ │ └── NewGameForm.jsx │ ├── Home │ │ ├── Categories.jsx │ │ ├── GameModes.jsx │ │ └── MainHome.jsx │ ├── PageError.jsx │ ├── PageFooter.jsx │ ├── PageLoading.jsx │ ├── Play │ │ ├── GameInfo.jsx │ │ ├── GameOver.jsx │ │ └── PlayHeader.jsx │ └── Questions │ │ ├── QuestionSlider.jsx │ │ ├── Questions.jsx │ │ ├── QuestionsNavbar.jsx │ │ └── Wildcards.jsx ├── helpers │ ├── gameConfig.js │ ├── getQuestions.js │ └── playSound.js ├── pages │ ├── _app.js │ ├── _document.js │ ├── api │ │ └── questions.js │ ├── index.js │ └── play │ │ └── index.js ├── store │ ├── useBoundStore.js │ ├── useQueries.js │ ├── useQuestions.js │ └── useWildcards.js └── styles │ └── globals.css └── tailwind.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | /source_code/node_modules 6 | /.pnp 7 | .pnp.js 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | .next 15 | /out/ 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | *.pem 23 | 24 | # debug 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | .pnpm-debug.log* 29 | 30 | # local env files 31 | .env*.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Cosmo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | Instagram 6 |
7 |
8 | 9 | # 🟥🟦 Quizi 🟨🟩 10 | 11 | A quiz/trivia game with different modes and categories that you can select, as well as wildcards to help you. The questions are generated by artificial intelligence using the [Cohere API](https://dashboard.cohere.ai/welcome/register). 12 | 13 | View Demo 14 | · 15 | Report Bug 16 | · 17 | Request Feature 18 |
19 | 20 | 21 | 22 | 23 |
24 | Table of contents 25 | 26 | - [About The Project](#about-the-project) 27 | - [Screenshots](#screenshots) 28 | - [Built With](#built-with) 29 | - [Getting Started](#getting-started) 30 | - [License](#license) 31 | - [Roadmap](#roadmap) 32 | - [Contact](#contact) 33 |
34 | 35 | 36 | ## About The Project 37 | 38 | Quizi is a quiz/trivia game made with with [Cohere](https://cohere.ai). You can select different game modes and topics, you also have wildcards. Cohere's AI will generate the questions and answers for you. 39 | 40 | > **Note:** Due to Cohere's policy change (from 100 to 5 free calls) now only some questions are generated by Cohere. The rest are pre-generated. 41 | 42 |

⬆️ Back to top

43 | 44 | 45 | 46 | ## Screenshots 47 | 48 | 49 | 50 | 53 | 56 | 59 | 60 | 61 | 64 | 67 | 70 | 71 | 72 | 75 | 78 | 81 | 82 |
51 | 52 | 54 | 55 | 57 | 58 |
62 | 63 | 65 | 66 | 68 | 69 |
73 | 74 | 76 | 77 | 79 | 80 |
83 | 84 |

⬆️ Back to top

85 | 86 | 87 | ### Built With 88 | 89 | List of the frameworks, libraries and tools used to build the project. 90 | 91 | * [Next.js](https://nextjs.org/) 92 | * [React.js](https://reactjs.org/) 93 | * [Zustand](https://github.com/pmndrs/zustand) For state management 94 | * [Cohere](https://dashboard.cohere.ai/welcome/register) For the generation of questions 95 | * [Vercel](https://vercel.com/) For hosting 96 | * [Tailwind CSS](https://tailwindcss.com/) For styling 97 | * [AnimatiSS](https://xsgames.co/animatiss/) For animations (title hover, correct and wrong answer) 98 | * [Patternpad](https://patternpad.com/editor.html) For the home background pattern 99 | * [Figma](https://www.figma.com/) For the design 100 | * [React icons](https://react-icons.github.io/react-icons/) For icons 101 | * [Iconify](https://iconify.design) For the answers letters icons 102 | * [Tabler Icons](https://tablericons.com) For the categories icons 103 | * [Canvas confetti](https://www.npmjs.com/package/canvas-confetti) For the confetti animation 104 | * [Vector Halftone Maker](https://halftone.xoihazard.com) For the halftone effect 105 | 106 |

⬆️ Back to top

107 | 108 | 109 | 110 | ## Getting Started 111 | 112 | 1. Clone or fork the repo 113 | ```sh 114 | git clone https://github.com/cosmoart/quiz-game 115 | ``` 116 | 2. Change directory to `source_code` 117 | ```sh 118 | cd source_code 119 | ``` 120 | 3. Install NPM packages 121 | ```sh 122 | npm install 123 | ``` 124 | 4. Run the project 125 | ```sh 126 | npm run dev 127 | ``` 128 | 129 | If you are in development environment all the questions are pre-generated, if you want to use the Cohere API you have to create a `.env.local` file with the Cohere API key at `source_code` and comment the `if` in `source_code/src/helpers/getQuestions.js`. You can get one Cohere Api key [here](https://dashboard.cohere.ai/welcome/register). 130 | 131 | The `.env.local` file should look like this: 132 | 133 | ``` 134 | COHERE_API_KEY=XXXXXXXXXXXXXXXXXX 135 | ``` 136 | 137 |

⬆️ Back to top

138 | 139 | 140 | 141 | 142 | ## License 143 | 144 | Distributed under the MIT License. See [`LICENSE.txt`](https://github.com/cosmoart/quiz-game/blob/main/LICENCE) for more information. 145 | 146 |

⬆️ Back to top

147 | 148 | 149 | 150 | ## Roadmap 151 | 152 | - [ ] ~~Circle wipe transition~~ 153 | - [x] Add offline mode 154 | - [x] Buttons sounds 155 | - [x] Win and Lose sounds 156 | - [ ] ~~Multi-language Support~~ 157 | - [ ] ~~PWA~~ 158 | - [x] Personalize the game over screen for infinite mode 159 | - [ ] ~~Personalize error page for API limit exceeded~~ 160 | 161 |

⬆️ Back to top

162 | 163 | 164 | ## Contact 165 | 166 | - My website - [cosmoart.vercel.app](https://cosmoart.vercel.app) 167 | - Twitter - [@CosmoArt0](https://twitter.com/cosmoart0) 168 | - Instagram - [@cosmo_art0](https://www.instagram.com/cosmo_art0/) 169 | 170 |

⬆️ Back to top

171 | -------------------------------------------------------------------------------- /readme/form_desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/form_desktop.webp -------------------------------------------------------------------------------- /readme/form_mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/form_mobile.webp -------------------------------------------------------------------------------- /readme/form_tablet.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/form_tablet.webp -------------------------------------------------------------------------------- /readme/header.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/header.webp -------------------------------------------------------------------------------- /readme/home_desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/home_desktop.webp -------------------------------------------------------------------------------- /readme/home_mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/home_mobile.webp -------------------------------------------------------------------------------- /readme/home_tablet.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/home_tablet.webp -------------------------------------------------------------------------------- /readme/play_classic_desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/play_classic_desktop.webp -------------------------------------------------------------------------------- /readme/play_classic_mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/play_classic_mobile.webp -------------------------------------------------------------------------------- /readme/play_classic_tablet.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/play_classic_tablet.webp -------------------------------------------------------------------------------- /readme/play_time_desktop.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/play_time_desktop.webp -------------------------------------------------------------------------------- /readme/play_time_mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/play_time_mobile.webp -------------------------------------------------------------------------------- /readme/play_time_tablet.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/readme/play_time_tablet.webp -------------------------------------------------------------------------------- /source_code/.env.example: -------------------------------------------------------------------------------- 1 | COHERE_API_KEY=XXXXXXXXXXXXXXXXXX -------------------------------------------------------------------------------- /source_code/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:react/recommended", 10 | "plugin:@next/next/recommended", 11 | "standard" 12 | ], 13 | "overrides": [], 14 | "parserOptions": { 15 | "ecmaFeatures": { 16 | "jsx": true 17 | }, 18 | "ecmaVersion": "latest", 19 | "sourceType": "module" 20 | }, 21 | "plugins": ["react"], 22 | "rules": { 23 | "indent": [1, "tab"], 24 | "no-tabs": 0, 25 | "react/react-in-jsx-scope": "off", 26 | "react/prop-types": "off", 27 | "no-unused-vars": 1, 28 | "react/no-unknown-property": [ 29 | 2, 30 | { 31 | "ignore": ["jsx", "global", "space"] 32 | } 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /source_code/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@/*": ["./src/*"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /source_code/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: false 4 | } 5 | 6 | module.exports = nextConfig 7 | -------------------------------------------------------------------------------- /source_code/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "quiz-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "license": "MIT", 6 | "lint": "eslint .", 7 | "scripts": { 8 | "dev": "next dev", 9 | "build": "next build", 10 | "start": "next start", 11 | "lint": "next lint" 12 | }, 13 | "dependencies": { 14 | "@next/font": "13.1.5", 15 | "cohere-ai": "5.0.2", 16 | "next": "13.1.5", 17 | "react": "18.2.0", 18 | "react-canvas-confetti": "1.3.0", 19 | "react-dom": "18.2.0", 20 | "react-icons": "4.7.1", 21 | "zustand": "^4.3.8" 22 | }, 23 | "devDependencies": { 24 | "autoprefixer": "^10.4.13", 25 | "eslint": "^8.34.0", 26 | "eslint-config-next": "^13.1.6", 27 | "eslint-config-standard": "^17.0.0", 28 | "eslint-plugin-import": "^2.27.5", 29 | "eslint-plugin-node": "^11.1.0", 30 | "eslint-plugin-promise": "^6.1.1", 31 | "eslint-plugin-react": "^7.32.2", 32 | "eslint-plugin-react-hooks": "^4.6.0", 33 | "postcss": "^8.4.21", 34 | "tailwindcss": "^3.2.4" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /source_code/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /source_code/public/bg-gamemodes.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/public/bg-home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/art.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/entertainment.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/general culture.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/geography.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/history.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/science.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/space.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /source_code/public/categories-icons/technology.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /source_code/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/public/letters/letter-a.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/public/letters/letter-b.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/public/letters/letter-c.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/public/letters/letter-d.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/public/play_bg.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/play_bg.webp -------------------------------------------------------------------------------- /source_code/public/sounds/correct_answer.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/correct_answer.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/pop-down.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/pop-down.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/pop-up-off.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/pop-up-off.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/pop-up-on.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/pop-up-on.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/pop.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/pop.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/switch-off.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/switch-off.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/switch-on.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/switch-on.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/win.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/win.mp3 -------------------------------------------------------------------------------- /source_code/public/sounds/wrong_answer.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cosmoart/quiz-game/68291b4498ed642ea804b1ec44570d743bafbae3/source_code/public/sounds/wrong_answer.mp3 -------------------------------------------------------------------------------- /source_code/src/assets/categories.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "aa", 4 | "name": "History", 5 | "color": "#e6c642" 6 | }, 7 | { 8 | "id": "ab", 9 | "name": "Entertainment", 10 | "color": "#f94e4e" 11 | }, 12 | { 13 | "id": "ac", 14 | "name": "Technology", 15 | "color": "#685af5" 16 | }, 17 | { 18 | "id": "ad", 19 | "name": "Geography", 20 | "color": "#3ce956" 21 | }, 22 | { 23 | "id": "ae", 24 | "name": "Art", 25 | "color": "#307de7" 26 | }, 27 | { 28 | "id": "af", 29 | "name": "Space", 30 | "color": "#a656fd" 31 | }, 32 | { 33 | "id": "ah", 34 | "name": "Science", 35 | "color": "#e857ed" 36 | }, 37 | { 38 | "id": "ag", 39 | "name": "General culture", 40 | "color": "#56cfef" 41 | } 42 | ] 43 | -------------------------------------------------------------------------------- /source_code/src/assets/fifty.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/src/assets/questions.json: -------------------------------------------------------------------------------- 1 | { 2 | "History": [ 3 | { 4 | "question": "In what year did the Berlin Wall fall?", 5 | "answers": ["1989", "1991", "1987", "1993"], 6 | "correctAnswer": "1989" 7 | }, 8 | { 9 | "question": "The first Roman emperor to become a Christian was:", 10 | "answers": ["Constantine", "Augustus", "Julius Caesar", "Nero"], 11 | "correctAnswer": "Constantine" 12 | }, 13 | { 14 | "question": "According to ancient legends, who founded Rome?", 15 | "answers": [ 16 | "Romulus and Remus", 17 | "Julius Caesar", 18 | "Augustus", 19 | "Marcus Aurelius" 20 | ], 21 | "correctAnswer": "Romulus and Remus" 22 | }, 23 | { 24 | "question": "Which civilization was responsible for the construction of Machu Picchu?", 25 | "answers": ["Aztecs", "Mayans", "Incas", "Inuit"], 26 | "correctAnswer": "Incas" 27 | }, 28 | { 29 | "question": "Who was the first woman to win a Nobel Prize?", 30 | "answers": [ 31 | "Marie Curie", 32 | "Mother Teresa", 33 | "Margaret Thatcher", 34 | "Indira Gandhi" 35 | ], 36 | "correctAnswer": "Marie Curie" 37 | }, 38 | { 39 | "question": "Which of these countries was not a part of the Soviet Union?", 40 | "answers": ["Ukraine", "Georgia", "Poland", "Belarus"], 41 | "correctAnswer": "Poland" 42 | }, 43 | { 44 | "question": "By what other name is the Eastern Roman Empire known?", 45 | "answers": [ 46 | "The Byzantine Empire", 47 | "The Ottoman Empire", 48 | "The Persian Empire", 49 | "The Holy Roman Empire" 50 | ], 51 | "correctAnswer": "The Byzantine Empire" 52 | }, 53 | { 54 | "question": "Which country was the first to send a satellite into space?", 55 | "answers": ["Russia", "USA", "China", "France"], 56 | "correctAnswer": "Russia" 57 | }, 58 | { 59 | "question": "Who was the first explorer to circumnavigate the globe?", 60 | "answers": [ 61 | "Christopher Columbus", 62 | "Vasco da Gama", 63 | "Magellan", 64 | "Francis Drake" 65 | ], 66 | "correctAnswer": "Magellan" 67 | }, 68 | { 69 | "question": "What was the name of the document that established the United Nations?", 70 | "answers": [ 71 | "The Treaty of Versailles", 72 | "The Geneva Convention", 73 | "The Charter of the United Nations", 74 | "The Magna Carta" 75 | ], 76 | "correctAnswer": "The Charter of the United Nations" 77 | }, 78 | { 79 | "question": "What is the name of the goddess of victory in Greek mythology?", 80 | "answers": ["Nike", "Puma", "Adidas", "Aphrodite"], 81 | "correctAnswer": "Nike" 82 | }, 83 | { 84 | "question": "How many operas did Beethoven compose?", 85 | "answers": ["1", "26", "165", "7"], 86 | "correctAnswer": "1" 87 | }, 88 | { 89 | "question": "What philosopher said \"I think, therefore I am\"?", 90 | "answers": ["Descartes", "Plato", "Aristotle", "Socrates"], 91 | "correctAnswer": "Descartes" 92 | }, 93 | { 94 | "question": "Which of these is not one of the Seven Wonders of the Ancient World?", 95 | "answers": [ 96 | "The Great Library of Alexandria", 97 | "Colossus of Rhodes", 98 | "Lighthouse of Alexandria", 99 | "Temple of Artemis" 100 | ], 101 | "correctAnswer": "The Great Library of Alexandria" 102 | }, 103 | { 104 | "question": "Which of these is not a Greek god or goddess?", 105 | "answers": ["Aphrodite", "Hera", "Athena", "Loki"], 106 | "correctAnswer": "Loki" 107 | } 108 | ], 109 | "Entertainment": [ 110 | { 111 | "question": "What is the name of the clown in the movie \"It\"?", 112 | "answers": ["Pennywise", "Bozo", "Krusty", "Joker"], 113 | "correctAnswer": "Pennywise" 114 | }, 115 | { 116 | "question": "What is the name of the fictional continent where the events of the TV series \"Game of Thrones\" take place?", 117 | "answers": ["Westeros", "Essos", "Sothoryos", "Ulthos"], 118 | "correctAnswer": "Westeros" 119 | }, 120 | { 121 | "question": "Who played the role of Batman in the 2008 movie \"The Dark Knight\"?", 122 | "answers": [ 123 | "Christian Bale", 124 | "Ben Affleck", 125 | "George Clooney", 126 | "Val Kilmer" 127 | ], 128 | "correctAnswer": "Christian Bale" 129 | }, 130 | { 131 | "question": "What is the name of the fairy in the Disney movie \"Peter Pan\"?", 132 | "answers": ["Tinker Bell", "Wendy", "Vidia", "Navi"], 133 | "correctAnswer": "Tinker Bell" 134 | }, 135 | { 136 | "question": "What is the name of the tiger that appears in the movie \"Life of Pi\"?", 137 | "answers": ["Richard Parker", "Tony", "Shere Khan", "Pi Patel"], 138 | "correctAnswer": "Richard Parker" 139 | }, 140 | { 141 | "question": "Who wrote the novel \"One Hundred Years of Solitude\"?", 142 | "answers": [ 143 | "Gabriel García Márquez", 144 | "Jorge Luis Borges", 145 | "Isabel Allende", 146 | "Octavio Paz" 147 | ], 148 | "correctAnswer": "Gabriel García Márquez" 149 | }, 150 | { 151 | "question": "Which of these is not a race or species in the video game \"World of Warcraft\"?", 152 | "answers": ["Kokiri", "Undead", "Huargen", "Troll"], 153 | "correctAnswer": "Kokiri" 154 | }, 155 | { 156 | "question": "How does Alice wane for the first time in the Disney movie \"Alice in Wonderland\"?", 157 | "answers": [ 158 | "She drinks a potion", 159 | "She eats a cake", 160 | "She falls down a hole", 161 | "She walks through a mirror" 162 | ], 163 | "correctAnswer": "She drinks a potion" 164 | }, 165 | { 166 | "question": "Who is the owner of Garfield in the comic strip \"Garfield\"?", 167 | "answers": ["Jon Arbuckle", "Odie", "Nermal", "Liz Wilson"], 168 | "correctAnswer": "Jon Arbuckle" 169 | }, 170 | { 171 | "question": "In which of these animes does the main character carry his sister in a box?", 172 | "answers": [ 173 | "Kimetsu no Yaiba", 174 | "Elfen Lied", 175 | "Code Geass", 176 | "Made in Abyss" 177 | ], 178 | "correctAnswer": "Kimetsu no Yaiba" 179 | }, 180 | { 181 | "question": "Where is the weak point of the titans in the anime \"Attack on Titan\"?", 182 | "answers": ["Nape", "Head", "Heart", "Back"], 183 | "correctAnswer": "Nape" 184 | }, 185 | { 186 | "question": "How many puppies does Perdita give birth to in the Disney movie \"101 Dalmatians\"?", 187 | "answers": ["15", "101", "99", "8"], 188 | "correctAnswer": "15" 189 | }, 190 | { 191 | "question": "How many dragon balls are there in the anime \"Dragon Ball\"?", 192 | "answers": ["7", "8", "6", "12"], 193 | "correctAnswer": "7" 194 | }, 195 | { 196 | "question": "In which of these movies are there aliens?", 197 | "answers": [ 198 | "The Great Wall", 199 | "Big Heroes 6", 200 | "Duplicity", 201 | "Braveheart" 202 | ], 203 | "correctAnswer": "The Great Wall" 204 | }, 205 | { 206 | "question": "What is the name of Misa Amane's shinigami in the anime \"Death Note\"?", 207 | "answers": ["Rem", "Ryuk", "Sidoh", "Gelus"], 208 | "correctAnswer": "Rem" 209 | } 210 | ], 211 | "Geography": [ 212 | { 213 | "question": "What is the capital city of Australia?", 214 | "answers": ["Sydney", "Melbourne", "Canberra", "Brisbane"], 215 | "correctAnswer": "Canberra" 216 | }, 217 | { 218 | "question": "How many stars appear on the flag of the People's Republic of China?", 219 | "answers": ["4", "5", "6", "3"], 220 | "correctAnswer": "5" 221 | }, 222 | { 223 | "question": "What continent is Saudi Arabia on?", 224 | "answers": ["Asia", "Africa", "Europe", "South America"], 225 | "correctAnswer": "Asia" 226 | }, 227 | { 228 | "question": "What is the name of the official language in China?", 229 | "answers": ["Mandarin", "Cantonese", "Hokkien", "Hakka"], 230 | "correctAnswer": "Mandarin" 231 | }, 232 | { 233 | "question": "Which of these European countries is further west?", 234 | "answers": ["Spain", "Italy", "Greece", "Germany"], 235 | "correctAnswer": "Spain" 236 | }, 237 | { 238 | "question": "How many oceans are there on Earth?", 239 | "answers": ["5", "6", "7", "8"], 240 | "correctAnswer": "5" 241 | }, 242 | { 243 | "question": "What is the capital of Colombia?", 244 | "answers": ["Bogotá", "Medellín", "Cali", "Barranquilla"], 245 | "correctAnswer": "Bogotá" 246 | }, 247 | { 248 | "question": "Which country is the smallest in the world", 249 | "answers": ["Vatican City", "Monaco", "Nauru", "Tuvalu"], 250 | "correctAnswer": "Vatican City" 251 | }, 252 | { 253 | "question": "What is the largest country in Africa by land area?", 254 | "answers": ["Algeria", "Sudan", "Libya", "Congo"], 255 | "correctAnswer": "Algeria" 256 | }, 257 | { 258 | "question": "What is the highest mountain in America?", 259 | "answers": [ 260 | "Mount Denali", 261 | "Mount Logan", 262 | "Mount Saint Elias", 263 | "Pico de Orizaba" 264 | ], 265 | "correctAnswer": "Mount Denali" 266 | }, 267 | { 268 | "question": "Which city is located both in Europe and Asia?", 269 | "answers": ["Istanbul", "Moscow", "Kiev", "Nicosia"], 270 | "correctAnswer": "Istanbul" 271 | }, 272 | { 273 | "question": "What is the name of the world's largest reef system, located in Australia?", 274 | "answers": [ 275 | "Great Barrier Reef", 276 | "Belize Barrier Reef", 277 | "Mesoamerican Barrier Reef", 278 | "Andros Barrier Reef" 279 | ], 280 | "correctAnswer": "Great Barrier Reef" 281 | }, 282 | { 283 | "question": "Which river is the longest in the world?", 284 | "answers": ["Nile", "Amazon", "Yangtze", "Mississippi"], 285 | "correctAnswer": "Amazon" 286 | }, 287 | { 288 | "question": "Which country is the largest by land area?", 289 | "answers": ["Russia", "Canada", "China", "United States"], 290 | "correctAnswer": "Russia" 291 | }, 292 | { 293 | "question": "How many states are part of the United States?", 294 | "answers": ["50", "51", "48", "53"], 295 | "correctAnswer": "50" 296 | }, 297 | { 298 | "question": "Which of these countries is not in Europe?", 299 | "answers": ["Georgia", "Moldova", "Armenia", "Azerbaijan"], 300 | "correctAnswer": "Armenia" 301 | }, 302 | { 303 | "question": "What is the official currency of India?", 304 | "answers": ["Rupee", "Ruble", "Rial", "Real"], 305 | "correctAnswer": "Rupee" 306 | }, 307 | { 308 | "question": "In which country is Mount Everest located?", 309 | "answers": ["Nepal", "China", "India", "Pakistan"], 310 | "correctAnswer": "Nepal" 311 | } 312 | ], 313 | "Science": [ 314 | { 315 | "question": "What is the chemical symbol for gold?", 316 | "answers": ["Au", "Ag", "Cu", "Fe"], 317 | "correctAnswer": "Au" 318 | }, 319 | { 320 | "question": "What is the triangle that has three equal sides called?", 321 | "answers": ["Equilateral", "Isosceles", "Scalene", "Right"], 322 | "correctAnswer": "Equilateral" 323 | }, 324 | { 325 | "question": "What is an oviparous?", 326 | "answers": [ 327 | "An animal that lays eggs", 328 | "An animal that gives birth", 329 | "An animal that flies", 330 | "An animal that lives in the water" 331 | ], 332 | "correctAnswer": "An animal that lays eggs" 333 | }, 334 | { 335 | "question": "Cartography is the study of what?", 336 | "answers": ["Maps", "Cars", "Cats", "Carpets"], 337 | "correctAnswer": "Maps" 338 | }, 339 | { 340 | "question": "If 50 is 100%, what is 90%?", 341 | "answers": ["45", "10", "100", "50"], 342 | "correctAnswer": "45" 343 | }, 344 | { 345 | "question": "How many legs does a fly have?", 346 | "answers": ["6", "4", "8", "2"], 347 | "correctAnswer": "6" 348 | }, 349 | { 350 | "question": "What is the smallest unit of matter?", 351 | "answers": ["Atom", "Molecule", "Cell", "Electron"], 352 | "correctAnswer": "Atom" 353 | }, 354 | { 355 | "question": "What element do all acids contain?", 356 | "answers": ["Hydrogen", "Oxygen", "Helium", "Nitrogen"], 357 | "correctAnswer": "Hydrogen" 358 | }, 359 | { 360 | "question": "What is the name of the process by which plants convert sunlight into energy?", 361 | "answers": [ 362 | "Photosynthesis", 363 | "Respiration", 364 | "Digestion", 365 | "Fermentation" 366 | ], 367 | "correctAnswer": "Photosynthesis" 368 | }, 369 | { 370 | "question": "What is the name of the force that pulls objects toward each other?", 371 | "answers": ["Gravity", "Magnetism", "Friction", "Electricity"], 372 | "correctAnswer": "Gravity" 373 | }, 374 | { 375 | "question": "What is the metal found in the center of the earth?", 376 | "answers": ["Iron", "Nickel", "Copper", "Zinc"], 377 | "correctAnswer": "Iron" 378 | }, 379 | { 380 | "question": "What are diamonds made of?", 381 | "answers": ["Carbon", "Glass", "Silver", "Platinum"], 382 | "correctAnswer": "Carbon" 383 | }, 384 | { 385 | "question": "What is the name of the process by which a solid turns into a gas without passing through the liquid state?", 386 | "answers": [ 387 | "Sublimation", 388 | "Evaporation", 389 | "Condensation", 390 | "Freezing" 391 | ], 392 | "correctAnswer": "Sublimation" 393 | }, 394 | { 395 | "question": "What is the name of the protein that gives skin, hair, and nails their strength?", 396 | "answers": ["Keratin", "Collagen", "Elastin", "Myosin"], 397 | "correctAnswer": "Keratin" 398 | }, 399 | { 400 | "question": "How many chemical elements are there on the periodic table?", 401 | "answers": ["118", "92", "104", "113"], 402 | "correctAnswer": "118" 403 | }, 404 | { 405 | "question": "What is the first element on the periodic table?", 406 | "answers": ["Hydrogen", "Helium", "Lithium", "Oxygen"], 407 | "correctAnswer": "Hydrogen" 408 | }, 409 | { 410 | "question": "What vitamin can be synthesized when exposed to sunlight?", 411 | "answers": ["Vitamin D", "Vitamin A", "Vitamin C", "Vitamin E"], 412 | "correctAnswer": "Vitamin D" 413 | }, 414 | { 415 | "question": "Every how many years does Halley's Comet pass the earth?", 416 | "answers": ["75", "86", "96", "106"], 417 | "correctAnswer": "75" 418 | }, 419 | { 420 | "question": "What is the only even prime number?", 421 | "answers": ["2", "14", "6", "8"], 422 | "correctAnswer": "2" 423 | }, 424 | { 425 | "question": "-3 + 10 ÷ 2", 426 | "answers": ["2", "1", "4", "3.5"], 427 | "correctAnswer": "2" 428 | }, 429 | { 430 | "question": "What does the gallon measure?", 431 | "answers": ["Volume", "Weight", "Distance", "Time"], 432 | "correctAnswer": "Volume" 433 | }, 434 | { 435 | "question": "What does the newton measure?", 436 | "answers": ["Force", "Weight", "Distance", "Time"], 437 | "correctAnswer": "Force" 438 | } 439 | ], 440 | "Technology": [ 441 | { 442 | "question": "Which company developed the programming language Java?", 443 | "answers": ["Sun Microsystems", "Microsoft", "Apple", "IBM"], 444 | "correctAnswer": "Sun Microsystems" 445 | }, 446 | { 447 | "question": "How many bits is a byte?", 448 | "answers": ["8", "4", "16", "32"], 449 | "correctAnswer": "8" 450 | }, 451 | { 452 | "question": "How many megabytes is a gigabyte?", 453 | "answers": [ 454 | "1024", 455 | "1000", 456 | "100", 457 | "Depends on the size of the file" 458 | ], 459 | "correctAnswer": "1024" 460 | }, 461 | { 462 | "question": "What is the name of the open-source operating system based on the Linux kernel?", 463 | "answers": ["Ubuntu", "Windows", "macOS", "Android"], 464 | "correctAnswer": "Ubuntu" 465 | }, 466 | { 467 | "question": "What is the name of the first computer?", 468 | "answers": ["ENIAC", "UNIVAC I", "Z1", "Colossus"], 469 | "correctAnswer": "ENIAC" 470 | }, 471 | { 472 | "question": "What is the name of the web browser developed by Google?", 473 | "answers": ["Chrome", "Firefox", "Safari", "Opera"], 474 | "correctAnswer": "Chrome" 475 | }, 476 | { 477 | "question": "What is the name of the programming language used to create web pages?", 478 | "answers": ["JavaScript", "CSS", "PhP", "Python"], 479 | "correctAnswer": "JavaScript" 480 | }, 481 | { 482 | "question": "The \".WAV\" is a format of?", 483 | "answers": ["Audio", "Video", "Image", "Document"], 484 | "correctAnswer": "Audio" 485 | }, 486 | { 487 | "question": "What is the name of the first computer virus?", 488 | "answers": ["Creeper", "Elk Cloner", "Rabbit", "Stoned"], 489 | "correctAnswer": "Creeper" 490 | }, 491 | { 492 | "question": "How many laws of robotics (or Asimov's laws) are there?", 493 | "answers": ["3", "4", "2", "6"], 494 | "correctAnswer": "3" 495 | }, 496 | { 497 | "question": "What is the name of the first video game console?", 498 | "answers": [ 499 | "Magnavox Odyssey", 500 | "Atari 2600", 501 | "Nintendo Entertainment System", 502 | "Sega Genesis" 503 | ], 504 | "correctAnswer": "Magnavox Odyssey" 505 | }, 506 | { 507 | "question": "What is the best-selling video game in history?", 508 | "answers": [ 509 | "Minecraft", 510 | "Tetris", 511 | "Wii Sports", 512 | "Grand Theft Auto V" 513 | ], 514 | "correctAnswer": "Minecraft" 515 | }, 516 | { 517 | "question": "What color are the pigs in the video game \"Angry Birds\"?", 518 | "answers": ["Green", "Red", "Yellow", "Blue"], 519 | "correctAnswer": "Green" 520 | }, 521 | { 522 | "question": "Which of these is not a champion in the video game \"League of Legends\"?", 523 | "answers": ["Gang-il", "Ahri", "Teemo", "Ryze"], 524 | "correctAnswer": "Gang-il" 525 | }, 526 | { 527 | "question": "How many points do the grapes give in the video game \"Pacman\"?", 528 | "answers": ["1000", "700", "100", "400"], 529 | "correctAnswer": "1000" 530 | }, 531 | { 532 | "question": "What is the name of the main character in the video game \"The Legend of Zelda\"?", 533 | "answers": ["Link", "Zelda", "Ganon", "Ganondorf"], 534 | "correctAnswer": "Link" 535 | } 536 | ], 537 | "Art": [ 538 | { 539 | "question": "Who painted the famous artwork \"The Starry Night\"?", 540 | "answers": [ 541 | "Vincent van Gogh", 542 | "Leonardo da Vinci", 543 | "Pablo Picasso", 544 | "Michelangelo" 545 | ], 546 | "correctAnswer": "Vincent van Gogh" 547 | }, 548 | { 549 | "question": "Which sculptor made the famous sculpture \"David?\"?", 550 | "answers": [ 551 | "Michelangelo", 552 | "Donatello", 553 | "Leonardo da Vinci", 554 | "Raphael" 555 | ], 556 | "correctAnswer": "Michelangelo" 557 | }, 558 | { 559 | "question": "What is the best-selling album in history?", 560 | "answers": [ 561 | "Thriller", 562 | "Back in Black", 563 | "The Dark Side of the Moon", 564 | "Bat Out of Hell" 565 | ], 566 | "correctAnswer": "Thriller" 567 | }, 568 | { 569 | "question": "How many strings does a guitar have?", 570 | "answers": ["Six", "Four", "Twelve", "Eight"], 571 | "correctAnswer": "Six" 572 | }, 573 | { 574 | "question": "What is the name of the famous statue that depicts the Greek goddess of love and beauty?", 575 | "answers": [ 576 | "Venus de Milo", 577 | "David", 578 | "The Thinker", 579 | "Laocoön and His Sons" 580 | ], 581 | "correctAnswer": "Venus de Milo" 582 | }, 583 | { 584 | "question": "What band is the author of the song \"Believer\"?", 585 | "answers": [ 586 | "Imagine Dragons", 587 | "Coldplay", 588 | "Maroon 5", 589 | "Linkin Park" 590 | ], 591 | "correctAnswer": "Imagine Dragons" 592 | }, 593 | { 594 | "question": "What is the name of the famous Italian artist who painted the ceiling of the Sistine Chapel?", 595 | "answers": [ 596 | "Michelangelo", 597 | "Leonardo da Vinci", 598 | "Raphael", 599 | "Sandro Botticelli" 600 | ], 601 | "correctAnswer": "Michelangelo" 602 | }, 603 | { 604 | "question": "Who is Don Quixote in love with in the play \"The Ingenious Hidalgo Don Quixote of La Mancha\"?", 605 | "answers": ["Dulcinea", "Maritornes", "Antonia", "Fernanda"], 606 | "correctAnswer": "Dulcinea" 607 | }, 608 | { 609 | "question": "What is the name of the famous ballet composed by Tchaikovsky?", 610 | "answers": [ 611 | "Swan Lake", 612 | "The Nutcracker", 613 | "Romeo and Juliet", 614 | "The Sleeping Beauty" 615 | ], 616 | "correctAnswer": "Swan Lake" 617 | }, 618 | { 619 | "question": "Who is the author of the famous book \"The Little Prince\"?", 620 | "answers": [ 621 | "Antoine de Saint-Exupéry", 622 | "Jean-Jacques Rousseau", 623 | "Voltaire", 624 | "Victor Hugo" 625 | ], 626 | "correctAnswer": "Antoine de Saint-Exupéry" 627 | }, 628 | { 629 | "question": "What architectural style is Notre Dame Cathedral?", 630 | "answers": ["Gothic", "Baroque", "Renaissance", "Neoclassical"], 631 | "correctAnswer": "Gothic" 632 | }, 633 | { 634 | "question": "Which famous playwright wrote the play \"Hamlet\"?", 635 | "answers": [ 636 | "William Shakespeare", 637 | "Tennessee Williams", 638 | "Arthur Miller", 639 | "Samuel Beckett" 640 | ], 641 | "correctAnswer": "William Shakespeare" 642 | }, 643 | { 644 | "question": "Which famous novel by George Orwell tells the story of a society where government surveillance and propaganda control all aspects of people's lives?", 645 | "answers": [ 646 | "1984", 647 | "Animal Farm", 648 | "Brave New World", 649 | "Fahrenheit 451" 650 | ], 651 | "correctAnswer": "1984" 652 | }, 653 | { 654 | "question": "Who is the author of the 'Harry Potter' book series?", 655 | "answers": [ 656 | "J.K. Rowling", 657 | "Stephen King", 658 | "George R.R. Martin", 659 | "Dan Brown" 660 | ], 661 | "correctAnswer": "J.K. Rowling" 662 | }, 663 | { 664 | "question": "In music, how many lines does a staff have?", 665 | "answers": ["Five", "Four", "Six", "Three"], 666 | "correctAnswer": "Five" 667 | } 668 | ], 669 | "Space": [ 670 | { 671 | "question": "What is the largest planet in our solar system?", 672 | "answers": ["Jupiter", "Saturn", "Uranus", "Neptune"], 673 | "correctAnswer": "Jupiter" 674 | }, 675 | { 676 | "question": "What is the name of the brightest star in the night sky?", 677 | "answers": [ 678 | "Sirius", 679 | "Proxima Centauri", 680 | "Betelgeuse", 681 | "Aldebaran" 682 | ], 683 | "correctAnswer": "Sirius" 684 | }, 685 | { 686 | "question": "What is the name of the only natural satellite of Earth?", 687 | "answers": ["Moon", "Mars", "Venus", "Jupiter"], 688 | "correctAnswer": "Moon" 689 | }, 690 | { 691 | "question": "What is the name of the first artificial satellite launched into space?", 692 | "answers": ["Sputnik 1", "Explorer 1", "Vanguard 1", "Vostok 1"], 693 | "correctAnswer": "Sputnik 1" 694 | }, 695 | { 696 | "question": "What is the speed of light approximately?", 697 | "answers": [ 698 | "300,000 km/s", 699 | "200,000 km/s", 700 | "100,000 km/s", 701 | "400,000 km/s" 702 | ], 703 | "correctAnswer": "300,000 km/s" 704 | }, 705 | { 706 | "question": "What is the name of the largest known asteroid in our solar system?", 707 | "answers": ["Ceres", "Vesta", "Pallas", "Hygiea"], 708 | "correctAnswer": "Ceres" 709 | }, 710 | { 711 | "question": "What is the name of the spacecraft that landed on Mars in 2021 as part of the Mars 2020 mission?", 712 | "answers": ["Perseverance", "Curiosity", "Opportunity", "Spirit"], 713 | "correctAnswer": "Perseverance" 714 | }, 715 | { 716 | "question": "How long does it take for sunlight to reach the earth?", 717 | "answers": ["8 minutes", "3.5 hours", "26 seconds", "10 seconds"], 718 | "correctAnswer": "8 minutes" 719 | }, 720 | { 721 | "question": "About how many stars are there in the solar system?", 722 | "answers": ["1", "100", "100,000", "Too many to count"], 723 | "correctAnswer": "1" 724 | }, 725 | { 726 | "question": "What is the most common matter in the universe?", 727 | "answers": ["Hydrogen", "Dark matter", "Helium", "Oxygen"], 728 | "correctAnswer": "Hydrogen" 729 | }, 730 | { 731 | "question": "About what temperature is it in space?", 732 | "answers": ["-270°C", "-120°C", "0°C", "38°C"], 733 | "correctAnswer": "-270°C" 734 | }, 735 | { 736 | "question": "Mainly which atoms do stars use in their fusion process?", 737 | "answers": ["Hydrogen", "Helium", "Oxygen", "Carbon"], 738 | "correctAnswer": "Hydrogen" 739 | }, 740 | { 741 | "question": "What is inside a black hole in the movie \"Interstellar\"?", 742 | "answers": [ 743 | "A fifth dimension", 744 | "A planet", 745 | "A spaceship", 746 | "Nothing" 747 | ], 748 | "correctAnswer": "A fifth dimension" 749 | }, 750 | { 751 | "question": "What is the geometric figure that describes the orbit of the planets?", 752 | "answers": ["Ellipse", "Circle", "Circumference", "Square"], 753 | "correctAnswer": "Ellipse" 754 | }, 755 | { 756 | "question": "How many moons does Mars have?", 757 | "answers": ["1", "2", "4", "Does not have"], 758 | "correctAnswer": "2" 759 | }, 760 | { 761 | "question": "What is the name of the first man to walk on the moon?", 762 | "answers": [ 763 | "Neil Armstrong", 764 | "Buzz Aldrin", 765 | "Alan Shepard", 766 | "Yuri Gagarin" 767 | ], 768 | "correctAnswer": "Neil Armstrong" 769 | } 770 | ], 771 | "General culture": [ 772 | { 773 | "question": "What part of the ship does the nautical term \"starboard\" refer to?", 774 | "answers": ["Right", "Left", "Front", "Back"], 775 | "correctAnswer": "Right" 776 | }, 777 | { 778 | "question": "Which river runs through London?", 779 | "answers": ["Thames", "Seine", "Danube", "Nile"], 780 | "correctAnswer": "Thames" 781 | }, 782 | { 783 | "question": "Who turns into Hulk?", 784 | "answers": [ 785 | "Bruce Banner", 786 | "Tony Stark", 787 | "Peter Parker", 788 | "Steve Rogers" 789 | ], 790 | "correctAnswer": "Bruce Banner" 791 | }, 792 | { 793 | "question": "How many players does a soccer team have on the field?", 794 | "answers": ["11", "10", "9", "12"], 795 | "correctAnswer": "11" 796 | }, 797 | { 798 | "question": "Which of these is a percussion instrument?", 799 | "answers": ["Drum", "Violin", "Flute", "Trumpet"], 800 | "correctAnswer": "Drum" 801 | }, 802 | { 803 | "question": "What color is the \"G\" in the Google logo?", 804 | "answers": ["Blue", "Red", "Yellow", "Green"], 805 | "correctAnswer": "Blue" 806 | }, 807 | { 808 | "question": "What holds the Oscar trophy figurine?", 809 | "answers": ["A sword", "A torch", "A book", "Nothing"], 810 | "correctAnswer": "A sword" 811 | }, 812 | { 813 | "question": "What instrument does Sherlock Holmes play?", 814 | "answers": ["Violin", "Flute", "Piano", "Guitar"], 815 | "correctAnswer": "Violin" 816 | }, 817 | { 818 | "question": "What is a falchion?", 819 | "answers": ["A sword", "A shield", "A helmet", "A spear"], 820 | "correctAnswer": "A sword" 821 | }, 822 | { 823 | "question": "How many hearts does an octopus have?", 824 | "answers": ["3", "2", "1", "0"], 825 | "correctAnswer": "3" 826 | }, 827 | { 828 | "question": "What does the Tin Woodman want in the novel \"The Wonderful Wizard of Oz\"?", 829 | "answers": ["A heart", "A brain", "Courage", "A home"], 830 | "correctAnswer": "A heart" 831 | }, 832 | { 833 | "question": "What color is the hair of the protagonist in the anime \"Death Note\"?", 834 | "answers": ["Black", "Blonde", "Red", "Brown"], 835 | "correctAnswer": "Brown" 836 | }, 837 | { 838 | "question": "What is the name of the holy book of Islam?", 839 | "answers": ["Quran", "Bible", "Torah", "Vedas"], 840 | "correctAnswer": "Quran" 841 | }, 842 | { 843 | "question": "How old is a lustrum?", 844 | "answers": ["5 years", "10 years", "15 years", "20 years"], 845 | "correctAnswer": "5 years" 846 | }, 847 | { 848 | "question": "How many sides does a hexagon have?", 849 | "answers": ["6", "5", "7", "8"], 850 | "correctAnswer": "6" 851 | } 852 | ] 853 | } 854 | -------------------------------------------------------------------------------- /source_code/src/assets/sound-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/src/assets/sound-on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/src/assets/star.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/src/assets/trophy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /source_code/src/components/Form/JsxForm.jsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image' 2 | import { defaultQuestions } from '@/helpers/gameConfig' 3 | import { BsSkipEndFill } from 'react-icons/bs' 4 | import { IoMdInfinite } from 'react-icons/io' 5 | import { FaHeart } from 'react-icons/fa' 6 | import fiftyImg from '@/assets/fifty.svg' 7 | import categoriesJSON from '@/assets/categories.json' 8 | import { useBoundStore } from '@/store/useBoundStore' 9 | 10 | export default function JsxForm ({ handleInputs, nowQueries }) { 11 | const { queries } = useBoundStore(state => state) 12 | 13 | const WILCARDS = [ 14 | { name: 'Skip question', icon: , amount: 1 }, 15 | { name: 'Delete two wrong questions', icon: fifty fifty, amount: 1 }, 16 | { name: 'Lives', icon: , amount: 1 } 17 | ] 18 | 19 | return ( 20 | <> 21 |
22 |
23 | Wilcards 24 |
    25 | { 26 | WILCARDS.map(({ name, icon, amount }) => ( 27 |
  • 28 |
    29 | {icon} 30 |
    31 | x{amount} 32 |
  • 33 | )) 34 | } 35 |
36 |
37 | 38 |
39 | Questions 40 | 41 |
42 | 43 | 44 |
45 | 46 |
47 | 48 | 49 | 50 | {nowQueries.infinitymode ? : nowQueries.questions} 51 | 52 |
53 |
54 | 55 |
56 | Time 57 | 58 |
59 | 60 | 61 |
62 | 63 |
64 | {[10, 20, 30, 60].map(time => ( 65 | 69 | ))} 70 |
71 |
72 |
73 | 74 |
75 | Categories 76 | 77 |
78 | {categoriesJSON.map(category => ( 79 | 89 | ))} 90 |
91 |
92 | 93 | ) 94 | } 95 | -------------------------------------------------------------------------------- /source_code/src/components/Form/NewGameForm.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef, useState } from 'react' 2 | import { useRouter } from 'next/router' 3 | 4 | import JsxForm from './JsxForm' 5 | import { IoCloseSharp } from 'react-icons/io5' 6 | import playSound from '@/helpers/playSound' 7 | import queryValidator from '@/helpers/gameConfig' 8 | import categoriesJSON from '@/assets/categories.json' 9 | import { useBoundStore } from '@/store/useBoundStore' 10 | 11 | export default function NewGameForm () { 12 | const { getQuestions, cleanQuestions, queries, setQueries, cleanWildCards } = useBoundStore(state => state) 13 | const [nowQueries, setNowQueries] = useState(queries) 14 | const router = useRouter() 15 | const dialog = useRef(null) 16 | 17 | useEffect(() => setNowQueries(queries), [queries]) 18 | 19 | useEffect(() => { 20 | if (router.isReady && router.pathname === '/play') { 21 | setQueries(queryValidator(router.query)) 22 | } 23 | }, [router.isReady]) 24 | 25 | function handleInputs (e) { 26 | if (e.target.name === 'infinitymode' || e.target.name === 'timemode') { 27 | e.target.checked ? playSound('pop-up-on') : playSound('pop-up-off') 28 | return setNowQueries({ ...nowQueries, [e.target.name]: e.target.name === 'infinitymode' ? !e.target.checked : e.target.checked }) 29 | } 30 | 31 | if (e.target.name === 'categories') { 32 | e.target.checked ? playSound('pop-up-on') : playSound('pop-up-off') 33 | return setNowQueries({ ...nowQueries, [e.target.name]: e.target.checked ? [...nowQueries.categories, e.target.value] : nowQueries.categories.filter(cat => cat !== e.target.value) }) 34 | } 35 | 36 | playSound('pop') 37 | setNowQueries({ ...nowQueries, [e.target.name]: e.target.value }) 38 | } 39 | 40 | function handleSubmit (e) { 41 | e.preventDefault() 42 | cleanQuestions() 43 | cleanWildCards() 44 | 45 | const query = Object.keys(nowQueries).map(key => `${key}=${nowQueries[key]}`).join('&') 46 | setQueries(queryValidator(nowQueries)) 47 | router.push({ pathname: '/play', query }) 48 | 49 | const cate = nowQueries.categories.map(cat => categoriesJSON.find(c => c.id === cat).name) 50 | if (router.pathname === '/play') getQuestions(cate, nowQueries.infinitymode ? 5 : nowQueries.questions) 51 | 52 | closeDialog() 53 | } 54 | 55 | function clickOutsideDialog (e) { 56 | const rect = dialog.current.getBoundingClientRect() 57 | if (e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom) { 58 | closeDialog() 59 | } 60 | } 61 | 62 | function closeDialog () { 63 | playSound('pop-down') 64 | dialog.current.classList.add('hide') 65 | function handleAnimationEnd () { 66 | dialog.current.classList.remove('hide') 67 | dialog.current.close() 68 | dialog.current.removeEventListener('animationend', handleAnimationEnd) 69 | } 70 | dialog.current.addEventListener('animationend', handleAnimationEnd) 71 | } 72 | 73 | return ( 74 | clickOutsideDialog(e)} id="newGameDialog" className='fixed top-1/2 w-5/6 sm:w-fit left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white text-slate-900 m-0 backdrop-blur-lg rounded-md py-9 px-8 md:px-11'> 75 | 78 | 79 |
e.preventDefault()} > 80 |
81 | 82 |
83 | 84 | 85 |
86 |
87 | ) 88 | } 89 | -------------------------------------------------------------------------------- /source_code/src/components/Home/Categories.jsx: -------------------------------------------------------------------------------- 1 | import categories from '@/assets/categories.json' 2 | import Image from 'next/image' 3 | 4 | export default function Categories () { 5 | return ( 6 |
7 |

Categories

8 |
    9 | {categories.map(category => ( 10 |
  • 11 | 12 |

    {category.name}

    13 |
  • 14 | ))} 15 |
16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /source_code/src/components/Home/GameModes.jsx: -------------------------------------------------------------------------------- 1 | import { ImInfinite } from 'react-icons/im' 2 | import { BiTimeFive } from 'react-icons/bi' 3 | import { TbDeviceGamepad2 } from 'react-icons/tb' 4 | 5 | const gameModes = [ 6 | { 7 | icon: , 8 | title: 'Classic', 9 | description: 'Complete questions without fail to win! You have wildcards that can help you' 10 | }, 11 | { 12 | icon: , 13 | title: 'Time', 14 | description: 'Complete questions within the time limit to win! You can use wildcards' 15 | }, 16 | { 17 | icon: , 18 | title: 'Infinite', 19 | description: 'Break your record by completing as many questions as you can! You can use wildcards' 20 | } 21 | ] 22 | 23 | export default function GameModes () { 24 | return ( 25 |
26 |

Game modes

27 | 38 |
39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /source_code/src/components/Home/MainHome.jsx: -------------------------------------------------------------------------------- 1 | import categories from '@/assets/categories.json' 2 | import PageFooter from '../PageFooter' 3 | import playSound from '@/helpers/playSound' 4 | 5 | export default function MainHome () { 6 | function handleTitleHover (e) { 7 | e.target.classList.add('jello-vertical') 8 | e.target.style.color = categories[Math.floor(Math.random() * categories.length)].color 9 | e.target.addEventListener('animationend', () => e.target.classList.remove('jello-vertical')) 10 | } 11 | 12 | const handleTitleLeave = (e) => (e.target.style.color = 'white') 13 | 14 | function handlePlay () { 15 | playSound('pop') 16 | document.getElementById('newGameDialog')?.showModal() 17 | } 18 | 19 | return ( 20 |
21 |
22 |

23 | {'Quizi'.split('').map((letter, index) => ( 24 | 25 | {letter} 26 | 27 | ))} 28 |

29 |
30 |

31 | Play an infinite number of possible questions! 32 |

33 |
34 | 37 | 38 |
39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /source_code/src/components/PageError.jsx: -------------------------------------------------------------------------------- 1 | import { useBoundStore } from '@/store/useBoundStore' 2 | import Link from 'next/link' 3 | import { BiErrorCircle, BiArrowBack } from 'react-icons/bi' 4 | 5 | export default function PageError () { 6 | const error = useBoundStore(state => state.error) 7 | 8 | return ( 9 |
10 |
11 | 12 |

13 | {error[1].statusCode || 500}: {(error[1].message && error[1].message) || 'Error occured'} 14 |

15 |

16 | Ooops! Something went wrong. Please try again later or play offline. 17 |

18 | 24 |
25 |
26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /source_code/src/components/PageFooter.jsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image' 2 | import playSound from '@/helpers/playSound' 3 | import soundOn from '../assets/sound-on.svg' 4 | import soundOff from '../assets/sound-off.svg' 5 | import { useEffect, useState } from 'react' 6 | import { MdInfo } from 'react-icons/md' 7 | import { GoAlert } from 'react-icons/go' 8 | import { BsFillStarFill } from 'react-icons/bs' 9 | 10 | export default function Footer ({ alert = false }) { 11 | const [sound, setSound] = useState(false) 12 | const [showInfo, setShowInfo] = useState(false) 13 | 14 | useEffect(() => { 15 | if (!localStorage.getItem('sound')) localStorage.setItem('sound', sound) 16 | else setSound(localStorage.getItem('sound') === 'true') 17 | }, []) 18 | 19 | useEffect(() => localStorage.setItem('sound', sound), [sound]) 20 | 21 | function handleClick (info = false) { 22 | info ? setShowInfo(!showInfo) : setSound(!sound) 23 | playSound('switch-on') 24 | } 25 | 26 | function handleSoundON () { 27 | setSound(true) 28 | localStorage.setItem('sound', true) 29 | playSound('switch-on') 30 | } 31 | 32 | return ( 33 |
34 | 64 |
65 | ) 66 | } 67 | -------------------------------------------------------------------------------- /source_code/src/components/PageLoading.jsx: -------------------------------------------------------------------------------- 1 | export default function PageLoading () { 2 | return ( 3 |
4 |
5 | 6 |
7 |
8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /source_code/src/components/Play/GameInfo.jsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image' 2 | import { AiFillInfoCircle } from 'react-icons/ai' 3 | import categories from '@/assets/categories.json' 4 | import { useState } from 'react' 5 | import { useBoundStore } from '@/store/useBoundStore' 6 | 7 | export default function GameInfo () { 8 | const { queries } = useBoundStore(state => state) 9 | const [showInfo, setShowInfo] = useState(false) 10 | 11 | const mode = queries.timemode && queries.infinitymode ? 'Time | Infinity' : !queries.timemode && !queries.infinitymode ? 'Classic' : queries.timemode ? 'Time' : 'Infinity' 12 | 13 | return ( 14 | <> 15 | 18 | 19 | 47 | 48 | 55 | 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /source_code/src/components/Play/GameOver.jsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image' 2 | import Link from 'next/link' 3 | 4 | import { AiFillCloseCircle, AiFillCheckCircle } from 'react-icons/ai' 5 | import { useCallback, useEffect, useRef } from 'react' 6 | import { IoCloseSharp } from 'react-icons/io5' 7 | import { BiArrowBack } from 'react-icons/bi' 8 | import trophyIcon from '@/assets/trophy.svg' 9 | 10 | import playSound from '@/helpers/playSound' 11 | import ReactCanvasConfetti from 'react-canvas-confetti' 12 | import { useBoundStore } from '@/store/useBoundStore' 13 | 14 | const canvasStyles = { 15 | position: 'fixed', 16 | pointerEvents: 'none', 17 | width: '100%', 18 | height: '100%', 19 | top: 0, 20 | left: 0, 21 | zIndex: 100 22 | } 23 | 24 | export default function GameOver () { 25 | const { queries, score, win } = useBoundStore(state => state) 26 | const refAnimationInstance = useRef(null) 27 | 28 | const getInstance = useCallback((instance) => { 29 | refAnimationInstance.current = instance 30 | }, []) 31 | 32 | const makeShot = useCallback((particleRatio, opts) => { 33 | refAnimationInstance.current && 34 | refAnimationInstance.current({ 35 | ...opts, 36 | origin: { y: 0.7 }, 37 | particleCount: Math.floor(200 * particleRatio) 38 | }) 39 | }, []) 40 | 41 | const fire = useCallback(() => { 42 | makeShot(0.25, { 43 | spread: 26, 44 | startVelocity: 55 45 | }) 46 | 47 | makeShot(0.2, { 48 | spread: 60 49 | }) 50 | 51 | makeShot(0.35, { 52 | spread: 100, 53 | decay: 0.91, 54 | scalar: 0.8 55 | }) 56 | 57 | makeShot(0.1, { 58 | spread: 120, 59 | startVelocity: 25, 60 | decay: 0.92, 61 | scalar: 1.2 62 | }) 63 | 64 | makeShot(0.1, { 65 | spread: 120, 66 | startVelocity: 45 67 | }) 68 | }, [makeShot]) 69 | 70 | useEffect(() => { 71 | if (win === true) { 72 | fire() 73 | playSound('win', 0.2) 74 | } 75 | }, [win]) 76 | 77 | function closeDialog () { 78 | playSound('pop', 0.2) 79 | document.getElementById('gameoverdialog').close() 80 | document.getElementById('gameoverbg').style.display = 'none' 81 | } 82 | 83 | function finalImage () { 84 | if (queries.infinitymode) return Trophy 85 | if (win === true) return 86 | return 87 | } 88 | 89 | function finalTitle () { 90 | if (queries.infinitymode) return 'Congratulations!' 91 | if (win === true) return 'You Win!' 92 | return 'You Lose!' 93 | } 94 | 95 | function finalText () { 96 | if (queries.infinitymode) return `You answered well ${score} questions!` 97 | if (win === true) return 'Congratulations! \nQuiz completed successfully.' 98 | return 'Better luck next time! \nYou can try again.' 99 | } 100 | 101 | return ( 102 | <> 103 |
104 | 105 | 106 | 107 | 108 | 111 | 112 |
113 | {finalImage()} 114 |

{finalTitle()}

115 |

116 | {finalText()} 117 |

118 |
119 | 120 | 121 | Go back 122 | 123 | 126 |
127 |
128 |
129 | 130 | ) 131 | } 132 | -------------------------------------------------------------------------------- /source_code/src/components/Play/PlayHeader.jsx: -------------------------------------------------------------------------------- 1 | import { BiArrowBack } from 'react-icons/bi' 2 | import { BsArrowRepeat } from 'react-icons/bs' 3 | import Link from 'next/link' 4 | import { useBoundStore } from '@/store/useBoundStore' 5 | 6 | export default function PlayHeader () { 7 | const { cleanQuestions, cleanWildCards } = useBoundStore(state => state) 8 | 9 | return ( 10 | 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /source_code/src/components/Questions/QuestionSlider.jsx: -------------------------------------------------------------------------------- 1 | import { useBoundStore } from '@/store/useBoundStore' 2 | import playSound from '@/helpers/playSound' 3 | import starIcon from '@/assets/star.svg' 4 | import Image from 'next/image' 5 | 6 | export default function QuestionSlider ({ changueCurrent, setTime, getAnotherQuestions }) { 7 | const { questions, queries, loadingInfinity, setUserAnswer, error, useLivesCard, setWin, wildCards, currentQuestion, setScore, win, score } = useBoundStore(state => state) 8 | 9 | function validateAnswer (e) { 10 | const correct = e.target.textContent === questions[currentQuestion - 1].correctAnswer 11 | 12 | e.target.parentNode.classList.add(correct ? 'shake-left-right' : 'vibrate') 13 | e.target.classList.add(correct ? 'correctAnswer' : 'wrongAnswer') 14 | 15 | document.querySelectorAll(`.answers-${currentQuestion} button`).forEach(answer => { 16 | answer.disabled = true 17 | if (!correct && answer.textContent === questions[currentQuestion - 1].correctAnswer) { 18 | answer.parentNode.classList.add('shake-left-right') 19 | answer.classList.add('correctAnswer') 20 | } 21 | }) 22 | 23 | playSound(correct ? 'correct_answer' : 'wrong_answer', 0.3) 24 | if (!queries.infinitymode) setUserAnswer(currentQuestion - 1, correct ? 1 : -1) 25 | 26 | if (queries.infinitymode) { 27 | if (correct) { 28 | if (score !== 1 && score % 5 === 0) getAnotherQuestions() 29 | } else { 30 | if (wildCards.lives > 0) { 31 | if (score !== 1 && score % 5 === 0) getAnotherQuestions() 32 | useLivesCard() 33 | } else return setWin(false) 34 | } 35 | } else { 36 | if (!correct) { 37 | if (wildCards.lives > 0) { 38 | useLivesCard() 39 | if (score === Number(queries.questions)) return setWin(true) 40 | } else return setWin(false) 41 | } else if (score === Number(queries.questions)) return setWin(true) 42 | } 43 | 44 | setTimeout(() => { 45 | setScore(score + 1) 46 | setTime(Number(queries.time)) 47 | if (queries.infinitymode && score !== 1 && score % 5 === 0) changueCurrent(1) 48 | else changueCurrent(currentQuestion + 1) 49 | }, 1000) 50 | } 51 | 52 | if (error[0]) { 53 | return
54 | An error occurred while loading the next questions... 55 |
56 | } 57 | 58 | if (loadingInfinity || !questions) { 59 | return
60 | Loading next questions... 61 |
62 | } 63 | 64 | return ( 65 |
66 | { 67 | questions.map((question, i) => { 68 | return ( 69 |
70 | { 71 | question.ia &&
72 | Question generated by AI 73 |
74 | } 75 |

76 | {question.question} 77 |

78 | 79 |
    80 | {question.answers.map((answer, j) => ( 81 |
  • 82 | 88 | 89 | {`Question 90 |
  • 91 | ))} 92 |
93 |
94 | ) 95 | }) 96 | } 97 |
98 | ) 99 | } 100 | -------------------------------------------------------------------------------- /source_code/src/components/Questions/Questions.jsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | import Wildcards from './Wildcards' 3 | import GameOver from '../Play/GameOver' 4 | import QuestionsNavbar from './QuestionsNavbar' 5 | import QuestionSlider from './QuestionSlider' 6 | 7 | import categories from '@/assets/categories.json' 8 | import playSound from '@/helpers/playSound' 9 | import { useBoundStore } from '@/store/useBoundStore' 10 | 11 | export default function Questions () { 12 | const { questions, loading, loadingInfinity, currentQuestion, setCurrentQuestion, setUserAnswer, win, score, setWin, setScore, wildCards, useLivesCard, queries, getQuestions } = useBoundStore(state => state) 13 | const [time, setTime] = useState(Number(queries.time)) 14 | 15 | useEffect(() => { 16 | const color = categories.find(cat => cat.name.toLowerCase() === questions[currentQuestion - 1]?.topic.toLowerCase())?.color 17 | color && (document.body.style.backgroundColor = color) 18 | 19 | function shortcuts (e) { 20 | if (!queries.infinitymode) { 21 | if (e.key === 'ArrowLeft' && currentQuestion > 1) changueCurrent(currentQuestion - 1) 22 | if (e.key === 'ArrowRight' && currentQuestion < score) changueCurrent(currentQuestion + 1) 23 | } 24 | 25 | if (e.key === 'a' || e.key === 'b' || e.key === 'c' || e.key === 'd') { 26 | const answer = ['a', 'b', 'c', 'd'].indexOf(e.key) 27 | if (answer !== -1) document.querySelector(`.answers-${queries.infinitymode ? currentQuestion : score} .answer-${answer + 1}`)?.click() 28 | } 29 | } 30 | 31 | document.addEventListener('keydown', shortcuts) 32 | return () => document.removeEventListener('keydown', shortcuts) 33 | }, [currentQuestion, score]) 34 | 35 | useEffect(() => { 36 | if (win !== undefined || !queries.timemode || loading || loadingInfinity) return 37 | const timeInterval = setInterval(() => setTime(time => time > 0 ? time - 1 : time), 1000) 38 | return () => clearInterval(timeInterval) 39 | }, [queries.timemode, win, loading, loadingInfinity]) 40 | 41 | useEffect(() => { 42 | if (win !== undefined || time > 0) return 43 | 44 | if (wildCards.lives < 1) { 45 | clickCorrectAnswer() 46 | setUserAnswer(score - 1, -1) 47 | playSound('wrong_answer', 0.3) 48 | setWin(false) 49 | } else { 50 | if (queries.infinitymode) { 51 | if (score !== 1 && score % 5 === 0) { 52 | clickCorrectAnswer() 53 | getAnotherQuestions() 54 | } else clickCorrectAnswer(true) 55 | } else { 56 | if (score === queries.questions) { 57 | setWin(true) 58 | clickCorrectAnswer() 59 | } else clickCorrectAnswer(true) 60 | } 61 | 62 | setUserAnswer(score - 1, 2) 63 | useLivesCard() 64 | playSound('correct_answer', 0.3) 65 | } 66 | }, [time]) 67 | 68 | function getAnotherQuestions () { 69 | setTimeout(() => { 70 | setTime(Number(queries.time)) 71 | changueCurrent(1) 72 | setScore(score + 1) 73 | const topics = categories.filter(category => queries.categories.find(cat => cat === category.id)).map(cat => cat.name) 74 | getQuestions(topics, 5, true) 75 | }, 1000) 76 | } 77 | 78 | function clickCorrectAnswer (addScore = false) { 79 | if (addScore) { 80 | setTimeout(() => { 81 | setScore(score + 1) 82 | setTime(Number(queries.time)) 83 | setUserAnswer(score - 1, 1) 84 | changueCurrent(score + 1) 85 | }, 1000) 86 | } 87 | 88 | document.querySelectorAll(`.answers-${score} button`).forEach(answer => { 89 | answer.disabled = true 90 | if (answer.textContent === questions[score - 1].correctAnswer) { 91 | answer.classList.add('correctAnswer') 92 | answer.parentNode.classList.add('shake-left-right') 93 | } 94 | }) 95 | } 96 | 97 | function changueCurrent (number) { 98 | if (number > questions.lenght || number < 1) return 99 | document.querySelectorAll('[id^="question-"]').forEach(question => { 100 | question.classList.remove('slide-left', 'slide-right') 101 | if (question.id !== `question-${number}`) { 102 | question.classList.add(Number(question.id.replace('question-', '')) < number ? 'slide-left' : 'slide-right') 103 | } 104 | }) 105 | setCurrentQuestion(number) 106 | } 107 | 108 | return ( 109 | <> 110 |
111 | 112 | 113 |
114 | 115 | {win !== undefined && } 116 | 117 | 118 | { 119 | queries.timemode &&
120 | {time} 121 | 122 | 123 | 124 |
125 | } 126 | 127 | ) 128 | } 129 | -------------------------------------------------------------------------------- /source_code/src/components/Questions/QuestionsNavbar.jsx: -------------------------------------------------------------------------------- 1 | import { useBoundStore } from '@/store/useBoundStore' 2 | 3 | export default function QuestionsNavbar ({ changueCurrent }) { 4 | const { queries, questions, currentQuestion, score } = useBoundStore(state => state) 5 | 6 | if (queries.infinitymode) { 7 | return
{score}
8 | } 9 | 10 | function buttonBg (i) { 11 | console.log(questions, i, questions[i]) 12 | let bg = 'bg-slate-600 hover:cursor-auto' 13 | if (i + 1 === score) bg = 'bg-white text-blue-500' 14 | if (questions[i].userAnswer === 1) bg = 'bg-green-500 !text-white' 15 | if (questions[i].userAnswer === -1) bg = 'bg-red-500 !text-white' 16 | if (questions[i].userAnswer === 2) bg = 'bg-blue-500 !text-white' 17 | if (i + 1 <= score) bg += ' cursor-pointer hover:scale-105' 18 | if (i + 1 === currentQuestion) bg += ' outline outline-offset-2 hover:outline-offset-4 outline-blue-500' 19 | return bg 20 | } 21 | 22 | return ( 23 |
    24 | {[...Array(parseInt(questions.length))].map((_, i) => ( 25 |
  1. 26 | 27 |
  2. 28 | ))} 29 |
30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /source_code/src/components/Questions/Wildcards.jsx: -------------------------------------------------------------------------------- 1 | import Image from 'next/image' 2 | import { BsSkipEndFill } from 'react-icons/bs' 3 | import fiftyImg from '@/assets/fifty.svg' 4 | import { FaHeart } from 'react-icons/fa' 5 | import { useBoundStore } from '@/store/useBoundStore' 6 | import { useEffect } from 'react' 7 | 8 | export default function Wildcards () { 9 | const { wildCards, useSkipCard, queries, win, useHalfCard, currentQuestion, score } = useBoundStore(state => state) 10 | 11 | useEffect(() => { 12 | function shortcuts (e) { 13 | if (e.key === 's') useSkipCard() 14 | if (e.key === 'h') useHalfCard() 15 | } 16 | document.addEventListener('keydown', shortcuts) 17 | return () => document.removeEventListener('keydown', shortcuts) 18 | }, []) 19 | 20 | function disabled (type) { 21 | const finalQuestion = queries.infinitymode ? (score % 5 === 0 ? 5 : score % 5) : score 22 | return wildCards[type] < 1 || win !== undefined || currentQuestion !== finalQuestion 23 | } 24 | 25 | return ( 26 | 52 | ) 53 | } 54 | -------------------------------------------------------------------------------- /source_code/src/helpers/gameConfig.js: -------------------------------------------------------------------------------- 1 | import categoriesJSON from '@/assets/categories.json' 2 | 3 | const MAX_QUESTIONS = 10 4 | const MIN_QUESTIONS = 4 5 | const TIMES = [10, 20, 30, 60] 6 | const DEFAULT_TIME = 20 7 | const DEFAULT_QUESTIONS = 5 8 | const INFINITY_MODE = false 9 | const TIME_MODE = false 10 | 11 | export default function queryValidator (query) { 12 | const { questions, time, infinitymode, timemode, categories } = query 13 | const urlQueries = {} 14 | 15 | if (questions && Number(questions)) { 16 | if (Number(questions) > MAX_QUESTIONS) urlQueries.questions = MAX_QUESTIONS 17 | else if (Number(questions) < MIN_QUESTIONS) urlQueries.questions = MIN_QUESTIONS 18 | else urlQueries.questions = Number(questions) 19 | } else urlQueries.questions = DEFAULT_QUESTIONS 20 | 21 | if (time && Number(time)) { 22 | if (Number(time) > TIMES[TIMES.length - 1]) urlQueries.time = TIMES[TIMES.length - 1] 23 | else if (Number(time) < TIMES[0]) urlQueries.time = TIMES[0] 24 | else urlQueries.time = Number(time) 25 | } else urlQueries.time = DEFAULT_TIME 26 | 27 | if (infinitymode) { 28 | if (infinitymode === 'true' || infinitymode === true) urlQueries.infinitymode = true 29 | else urlQueries.infinitymode = false 30 | } else urlQueries.infinitymode = INFINITY_MODE 31 | 32 | if (timemode) { 33 | if (timemode === 'true' || timemode === true) urlQueries.timemode = true 34 | else urlQueries.timemode = false 35 | } else urlQueries.timemode = TIME_MODE 36 | 37 | if (categories) { 38 | const categoriesArray = typeof categories === 'string' ? categories.split(',') : categories 39 | const categoriesArrayFiltered = categoriesArray.filter(category => categoriesJSON.map(category => category.id).includes(category)) 40 | if (categoriesArrayFiltered.length > 0) urlQueries.categories = categoriesArrayFiltered 41 | else urlQueries.categories = categoriesJSON.map(category => category.id) 42 | } else urlQueries.categories = categoriesJSON.map(category => category.id) 43 | 44 | return urlQueries 45 | } 46 | 47 | export const defaultQuestions = { 48 | minQuestions: MIN_QUESTIONS, 49 | maxQuestions: MAX_QUESTIONS 50 | } 51 | 52 | export const defaultQuery = { 53 | questions: DEFAULT_QUESTIONS, 54 | time: DEFAULT_TIME, 55 | infinitymode: INFINITY_MODE, 56 | timemode: TIME_MODE, 57 | categories: categoriesJSON.map(category => category.id) 58 | } 59 | -------------------------------------------------------------------------------- /source_code/src/helpers/getQuestions.js: -------------------------------------------------------------------------------- 1 | import offlineQuestions from '@/assets/questions.json' 2 | 3 | const randomArray = (arr) => arr.toSorted(() => 0.5 - Math.random()) 4 | 5 | export default async function getQuestions (topics, qNumber) { 6 | const randomTopics = randomArray(topics) 7 | const messyTopics = [] 8 | for (let i = 0; i < qNumber; i++) messyTopics.push(randomTopics[i % topics.length]) 9 | 10 | function getOfflineQuestions () { 11 | const questionsPerTopic = {} 12 | messyTopics.forEach(topic => { 13 | questionsPerTopic[topic] = (questionsPerTopic[topic] || 0) + 1 14 | }) 15 | 16 | const questions = [] 17 | Object.keys(questionsPerTopic).forEach(topic => { 18 | randomArray(offlineQuestions[topic]).slice(0, questionsPerTopic[topic]).forEach(question => { 19 | questions.push({ 20 | ...question, 21 | topic, 22 | answers: randomArray(question.answers), 23 | userAnswer: undefined, 24 | ia: false 25 | }) 26 | }) 27 | }) 28 | 29 | return questions 30 | } 31 | 32 | if (process.env.NODE_ENV === 'development') { 33 | return new Promise((resolve, reject) => { 34 | setTimeout(() => { 35 | // const error = new Error('Custom error') 36 | // error.statusCode = 350 37 | // reject(error) 38 | 39 | resolve(randomArray(getOfflineQuestions())) 40 | }, 1 * 1000) 41 | }) 42 | } 43 | 44 | const iaQuestions = fetch('/api/questions', { 45 | method: 'POST', 46 | headers: { 47 | 'Content-Type': 'application/json' 48 | }, 49 | body: JSON.stringify({ topics: messyTopics.slice(0, 3) }) 50 | }).then(res => res.json()) 51 | .then(data => { 52 | if (data.statusCode >= 400) { 53 | const error = new Error(data.message) 54 | error.statusCode = data.status 55 | throw error 56 | } else return data 57 | }) 58 | .catch(err => { 59 | console.log(err) 60 | throw err 61 | }) 62 | 63 | return iaQuestions 64 | .then(iaQuestions => randomArray([ 65 | ...iaQuestions, 66 | ...getOfflineQuestions().slice(iaQuestions.length) 67 | ])) 68 | .catch(() => randomArray(getOfflineQuestions())) 69 | } 70 | -------------------------------------------------------------------------------- /source_code/src/helpers/playSound.js: -------------------------------------------------------------------------------- 1 | export default function playSound (sound, volume = 0.25) { 2 | if (localStorage.getItem('sound') === 'true') { 3 | const audio = new Audio(`/sounds/${sound}.mp3`) 4 | audio.volume = volume 5 | audio.play() 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /source_code/src/pages/_app.js: -------------------------------------------------------------------------------- 1 | import '@/styles/globals.css' 2 | import { Rubik } from '@next/font/google' 3 | import Head from 'next/head' 4 | import NewGameForm from '@/components/Form/NewGameForm' 5 | const rubik = Rubik({ subsets: ['latin'] }) 6 | 7 | export default function App ({ Component, pageProps }) { 8 | return ( 9 | <> 10 | 11 | 12 | 13 | 14 | 15 | 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /source_code/src/pages/_document.js: -------------------------------------------------------------------------------- 1 | import { Html, Head, Main, NextScript } from 'next/document' 2 | 3 | export default function Document () { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | {/* */} 11 | 12 | 13 | 14 | 15 | 16 | {/* */} 17 | 18 | 19 | 20 | 21 | 22 | 23 | {/* */} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /source_code/src/pages/api/questions.js: -------------------------------------------------------------------------------- 1 | import offlineQuestions from '@/assets/questions.json' 2 | const cohere = require('cohere-ai') 3 | cohere.init(process.env.COHERE_API_KEY) 4 | 5 | function defaultPromt () { 6 | const topics = Object.keys(offlineQuestions) 7 | const random3Topics = topics.sort(() => Math.random() - Math.random()).slice(0, 3) 8 | const randomQuestions = random3Topics.map(topic => { 9 | const randomQuestion = { 10 | ...offlineQuestions[topic][Math.floor(Math.random() * offlineQuestions[topic].length)], 11 | topic 12 | } 13 | return randomQuestion 14 | }) 15 | 16 | const text = randomQuestions.reduce((acc, question, index) => { 17 | const questionText = `question: ${question.question}\ntopic: ${question.topic}\n${question.answers.map(answer => `-${answer}`).join('\n')}\ncorrect: ${question.correctAnswer}\n\n` 18 | if (index === randomQuestions.length - 1) return acc + questionText.slice(0, -1) 19 | return acc + questionText 20 | }, '') 21 | 22 | return 'Generate 3 questions, ' + random3Topics.map(topic => `1 about ${topic}`).join(', ') + '. Each question has 4 answers (1 correct and 3 incorrect).\n---\n' + text + '---\n' 23 | } 24 | 25 | export default function handler (req, res) { 26 | if (req.method !== 'POST') return res.status(405).json({ message: 'Only POST requests allowed', statusCode: 405 }) 27 | if (!req.body.topics) return res.status(400).json({ message: 'Topics are required', statusCode: 400 }) 28 | 29 | const promt = defaultPromt() + defaultPromt() + 'Generate 3 questions, ' + req.body.topics.map(topic => `1 about ${topic}`).join(', ') + '. Each question has 4 answers (1 correct and 3 incorrect).\n---' 30 | 31 | setTimeout(() => { 32 | res.status(500).json({ message: 'Request timed out', statusCode: 500 }) 33 | }, 10 * 1000) 34 | 35 | cohere.generate({ 36 | model: 'command', 37 | prompt: promt, 38 | max_tokens: 450, 39 | temperature: 0.8, 40 | k: 0, 41 | stop_sequences: ['---'], 42 | return_likelihoods: 'NONE' 43 | }) 44 | .then(response => { 45 | if (response.statusCode >= 400) { 46 | return res.status(500).json({ 47 | message: response.body.message || 'Something went wrong', 48 | statusCode: response.statusCode || 500 49 | }) 50 | } 51 | res.status(200).json(response.body.generations[0].text.split('\n\n').map(question => { 52 | if (question.startsWith('\n')) question = question.slice(1) 53 | if (question.endsWith('\n')) question = question.slice(0, -1) 54 | const questionArray = question.split('\n') 55 | const questionObject = { 56 | question: questionArray[0].split('question: ')[1]?.trim(), 57 | topic: questionArray[1].split('topic: ')[1]?.trim(), 58 | answers: questionArray.slice(2, 6).map(answer => answer.split('-')[1]?.trim()), 59 | correctAnswer: questionArray[6].split('correct: ')[1]?.trim(), 60 | userAnswer: undefined, 61 | ia: true 62 | } 63 | return questionObject 64 | })) 65 | }) 66 | .catch(err => { 67 | console.log(err) 68 | const message = err.body.message || 'Something went wrong' 69 | const statusCode = err.statusCode || 500 70 | return res.status(500).json({ message, statusCode }) 71 | }) 72 | } 73 | -------------------------------------------------------------------------------- /source_code/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from 'next/head' 2 | import MainHome from '@/components/Home/MainHome' 3 | import GameModes from '@/components/Home/GameModes' 4 | import Categories from '@/components/Home/Categories' 5 | import { useEffect } from 'react' 6 | 7 | export default function Main () { 8 | useEffect(() => { window.onbeforeunload = () => null }, []) 9 | 10 | return ( 11 | <> 12 | 13 | Quizi 14 | 15 | 16 | 17 | 18 | 30 | 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /source_code/src/pages/play/index.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react' 2 | import { useRouter } from 'next/router' 3 | import Head from 'next/head' 4 | 5 | import PageLoading from '@/components/PageLoading' 6 | import PageError from '@/components/PageError' 7 | import PlayHeader from '@/components/Play/PlayHeader' 8 | import GameInfo from '@/components/Play/GameInfo' 9 | import Footer from '@/components/PageFooter' 10 | import Questions from '@/components/Questions/Questions' 11 | 12 | import queryValidator from '@/helpers/gameConfig' 13 | import categories from '@/assets/categories.json' 14 | import { useBoundStore } from '@/store/useBoundStore' 15 | 16 | export default function Play () { 17 | const { loading, error, getQuestions, setQueries } = useBoundStore(state => state) 18 | const router = useRouter() 19 | 20 | useEffect(() => { 21 | if (router.isReady) { 22 | const validQuery = queryValidator(router.query) 23 | const cate = validQuery.categories.map(cat => categories.find(c => c.id === cat).name) 24 | setQueries(validQuery) 25 | getQuestions(cate, validQuery.infinitymode ? 5 : validQuery.questions) 26 | } 27 | }, [router.isReady]) 28 | 29 | useEffect(() => { window.onbeforeunload = () => 'Are you sure you want to leave?' }, []) 30 | 31 | return ( 32 | <> 33 | Quizi | Play 34 | {loading && } 35 | {error[0] && } 36 | {!loading && !error[0] && <> 37 | 38 | 39 | 40 |