diff --git a/README.md b/README.md index 8e4b75e9..283bf555 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,21 @@ # 🧠🤔 KiWiq 🥝❓📚 Visit our page [here!!!](http://kiwiq.run.place/). -WIQ is a quiz game project inspired by the engaging and thought-provoking show "Saber y Ganar." +KiWiq is a quiz game project inspired by the engaging and thought-provoking show "Saber y Ganar." We aim to create a platform that not only challenges your knowledge but also sparks curiosity and the thrill of discovery. ## What Sets WIQ Apart -🤔 Thoughtful Questions: Dive into a world of intriguing and diverse questions, all generated procedurally using WikiData. -🌐 Encourage to improve: WIQ lets you keep track of your score to see in which areas you need to improve. +🤔 Thoughtful Questions: Dive into a world of intriguing and diverse questions, all generated procedurally using WikiData. -😭 It works! after the final version final re-final (FINAL) true (final) (hotfix) +🌐 Encourage to improve: KiWiq lets you keep track of your score to motivate you into learning more. -## Features -🏆 Adaptable difficulty: You can adjust the difficulty to push your limits. +🔣 Question diversity: KiWiq offers you a variety of questions so you can test your knowledge in a variety of fields. -🌐 Multiplayer: Compete with friends and strangers to prove you are the best. +## Features +🏆 Adaptable difficulty: You can adjust the difficulty to push your limits. -🌐 Localized: Available in Spanish and English. +🌍 Localized: Available in Spanish and English. ## Contributors Contributor | Contact @@ -43,7 +42,7 @@ This repo is a basic application composed of several components. Component | Route | Description -- | -- | -- Backend/API | `api/` | The main backend service, implemented in Java SpringBoot. It serves all requests from the frontend, and it doubles as main API. It also has a JWT-based authentication system. -Question generator | `questiongenerator/` | A SpringBoot-based service, ran alongside the main backend service, that generates questions and inserts them into the database +Question generator | `questiongenerator/` | A Java program that generates questions and inserts them into the database, from where they are fetched by the API. Webapp | `webapp/` | Our own frontend to the backend. It is implemented in React 18. *** diff --git a/docs/diagrams/BusinessContextDiagram.puml b/docs/diagrams/BusinessContextDiagram.puml deleted file mode 100644 index 0fdbcad7..00000000 --- a/docs/diagrams/BusinessContextDiagram.puml +++ /dev/null @@ -1,23 +0,0 @@ -@startuml -!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml -!include - -title Context Diagram for the WIQ System -AddElementTag("Person", $bgColor="#salmon", $fontColor="#white") -AddElementTag("Internal system", $bgColor="#peachpuff", $fontColor="#963b17") -AddElementTag("External system", $bgColor="#darksalmon", $fontColor="#white") - -'Containers -Person(player, Player,"An authenticated player that wants to play WIQ games", $tags="Person") - -Container(wiq, "WIQ Application","", "Application that allows the users to play WIQ games", $tags="Internal system") - -Container(question_generator, "Question Generator Module","", "Organizes everything related with questions", $tags="Internal system") - -System_Ext(wikidata,"WikiData API","Contains the information used for the question generation", $tags="External system") - -'RELATIONS -Rel(player,wiq,"Plays games") -Rel(wiq, question_generator, "Asks for questions and answers") -Rel(question_generator,wikidata,"Asks for data for question generation") -@enduml \ No newline at end of file diff --git a/docs/diagrams/TechnicalContextDiagram.puml b/docs/diagrams/TechnicalContextDiagram.puml deleted file mode 100644 index 2d2e0f1a..00000000 --- a/docs/diagrams/TechnicalContextDiagram.puml +++ /dev/null @@ -1,27 +0,0 @@ -@startuml -!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml -!include - -title Context Diagram for the WIQ System -AddElementTag("Person", $bgColor="#salmon", $fontColor="#white") -AddElementTag("Internal system", $bgColor="#peachpuff", $fontColor="#963b17") -AddElementTag("External system", $bgColor="#darksalmon", $fontColor="#white") - -'Containers -Person(player, Player's Browser,"Preferred browser (Firefox, Chrome, Opera...)") - -System_Boundary(wiq,"WIQ Server"){ - Container(web_app, "WIQ Client", "React, Typescript", "nginx web server", $tags="Internal system") - Container(backend_api, "WIQ REST API","Java SpringBoot 3",".jar file", $tags="Internal system") - ContainerDb(database,"WIQ Database","PostgreSQL","PostgreSQL docker container", $tags="Internal system") -} -System_Ext(wikidata,"WikiData API","REST API", $tags="External system") - -'RELATIONS -Rel(player,web_app,"Uses","HTTPS") -Rel(backend_api,wikidata,"Asks for data","SPARQL,HTTPS") -Rel(web_app,backend_api,"Asks for user/game information","JSON,HTTPS") -Rel(backend_api,database,"Stores game/user information","JPA") - - -@enduml \ No newline at end of file diff --git a/docs/diagrams/c4/C4-Level1.puml b/docs/diagrams/c4/C4-Level1.puml new file mode 100644 index 00000000..289451f5 --- /dev/null +++ b/docs/diagrams/c4/C4-Level1.puml @@ -0,0 +1,20 @@ +@startuml +!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml +!include + +title Context Diagram for the Kiwiq System (C4 Level 1) +AddElementTag("Person", $bgColor="#darkgreen", $fontColor="#white") +AddElementTag("Internal system", $bgColor="#darkseagreen", $fontColor="#003300") +AddElementTag("External system", $bgColor="#gray", $fontColor="#white") +'Containers +Person(player, Player,"An authenticated player that wants to play Kiwiq games", $tags="Person") + +Container(kiwiq, "Kiwiq System","", "System that allows the users to play Kiwiq games", $tags="Internal system") + + +System_Ext(wikidata,"WikiData API","Contains the information used for the question generation", $tags="External system") + +'RELATIONS +Rel(player,kiwiq,"Plays games") +Rel(kiwiq,wikidata,"Asks for data for question generation") +@enduml \ No newline at end of file diff --git a/docs/diagrams/c4/C4-Level2.puml b/docs/diagrams/c4/C4-Level2.puml new file mode 100644 index 00000000..e6ff9dca --- /dev/null +++ b/docs/diagrams/c4/C4-Level2.puml @@ -0,0 +1,31 @@ +@startuml +!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml +!include + +title Container Diagram for the Kiwiq System (C4 Level 2) +AddElementTag("Person", $bgColor="#darkgreen", $fontColor="#white") +AddElementTag("Internal system", $bgColor="#darkseagreen", $fontColor="#003300") +AddElementTag("External system", $bgColor="#gray", $fontColor="#white") +AddElementTag("Database", $bgColor="#darkgreen", $fontColor="#white") +'Containers +Person(player, Player's Browser,"Preferred browser (Firefox, Chrome, Opera...)") + +System_Boundary(wiq,"Kiwiq Server"){ + Container(proxy,"Proxy","Nginx","Nginx web server", $tags="Internal system") + Container(web_app, "Kiwiq Client", "React, Typescript", "nginx web server", $tags="Internal system") + Container(backend_api, "Kiwiq REST API","Java SpringBoot 3",".jar file", $tags="Internal system") + Container(question_generator,"Question generator","Java, JPA",".jar file",$tags="Internal system") + ContainerDb(database,"Kiwiq Database","PostgreSQL","PostgreSQL docker container", $tags="Database") +} +System_Ext(wikidata,"WikiData API","REST API", $tags="External system") + +'RELATIONS +Rel(player,proxy,"Uses","HTTPS") +Rel(proxy,web_app,"Serves","HTTPS") +Rel(question_generator,wikidata,"Asks for data","SPARQL,HTTPS") +Rel(web_app,backend_api,"Asks for user/game information","JSON,HTTPS") +Rel(question_generator, database,"Stores questions ","JPA") +Rel(backend_api,database,"Stores game/user information","JPA") + + +@enduml \ No newline at end of file diff --git a/docs/diagrams/c4/C4-Level3.puml b/docs/diagrams/c4/C4-Level3.puml new file mode 100644 index 00000000..39eb3eac --- /dev/null +++ b/docs/diagrams/c4/C4-Level3.puml @@ -0,0 +1,48 @@ +@startuml +!includeurl https://raw.githubusercontent.com/RicardoNiepel/C4-PlantUML/master/C4_Container.puml +!include +!include +title Container Diagram for the Kiwiq System (C4 Level 3) +AddElementTag("Person", $bgColor="#darkgreen", $fontColor="#white") +AddElementTag("Internal system", $bgColor="#darkseagreen", $fontColor="#003300") +AddElementTag("External system", $bgColor="#gray", $fontColor="#white") +AddElementTag("Database", $bgColor="#darkgreen", $fontColor="#white") +AddElementTag("Component", $bgColor="#darkolivegreen", $fontColor="#white") +'Containers +Person(player, Player's Browser,"Preferred browser (Firefox, Chrome, Opera...)") + +System_Boundary(wiq,"Kiwiq Server"){ + Container(proxy,"Proxy","Nginx","Nginx web server", $tags="Internal system") + Container(web_app, "Kiwiq Client", "React, Typescript", "nginx web server", $tags="Internal system") + System_Boundary(backend_api,"Kiwiq REST API"){ + Component(auth,"Authentication module") + Component(games,"Game module") + Component(questions,"Question module") + Component(statistics,"Statistics module") + } + + Container(question_generator,"Question generator","Java, JPA",".jar file",$tags="Internal system") + ContainerDb(database,"Kiwiq Database","PostgreSQL","PostgreSQL docker container", $tags="Database") +} + +System_Ext(wikidata,"WikiData API","REST API", $tags="External system") + +'RELATIONS +Rel(player,proxy,"Uses","HTTPS") +Rel(proxy,web_app,"Serves","HTTPS") +Rel(question_generator,wikidata,"Asks for data","SPARQL,HTTPS") +Rel(question_generator, database,"Stores questions ","JPA") + +Rel(web_app,questions,"Asks for question information","JSON,HTTPS") +Rel(web_app,games,"Plays a game","JSON,HTTPS") +Rel(web_app,auth,"Ask for login and register","JSON,HTTPS") +Rel(web_app,statistics,"Asks for statistics","JSON,HTTPS") + + +Rel(games,database,"Stores game/user information","JPA") + +Rel(games,questions,"Gets questions") +Rel(questions,database,"Stores game/user information","JPA") +Rel(statistics,database,"Stores game/user information","JPA") +Rel(auth,database,"Stores game/user information","JPA") +@enduml \ No newline at end of file diff --git a/docs/diagrams/deployment/DeploymentDiagram.puml b/docs/diagrams/deployment/DeploymentDiagram.puml deleted file mode 100644 index 19174a75..00000000 --- a/docs/diagrams/deployment/DeploymentDiagram.puml +++ /dev/null @@ -1,36 +0,0 @@ -@startuml - -title WIQ Deployment View - -legend right - |Color| Type | - |<#PeachPuff>| WIQ Server | - |<#DarkSalmon>| External Service | -end legend - -node "Server Hosting WIQ" #PeachPuff { - node "WIQ WebApp Server"{ - component "WIQ React Application" - } - node "WIQ API" { - component "WIQ_API.jar" - } - node "PostgreSQL Docker" { - database "WIQ Database" - } - node "Question generator" { - component "Question_Generator.jar" - } -} -node "User Computer" #DarkSalmon{ - frame "Web Client" -} -node "WikiData Server" #DarkSalmon { - frame "WikiData REST API" -} -"Web Client" ..> "WIQ React Application" : "HTTPS" -"WIQ React Application" ..> "WIQ_API.jar" : "HTTPS" -"WIQ_API.jar" ..> "WIQ Database" : "JPA" -"Question_Generator.jar" ..> "WikiData REST API" : "HTTPS, SPARQL" -"Question_Generator.jar" ..> "WIQ Database" : "JPA" -@enduml \ No newline at end of file diff --git a/docs/diagrams/deployment/DeploymentDiagramLevel1.puml b/docs/diagrams/deployment/DeploymentDiagramLevel1.puml new file mode 100644 index 00000000..f361abf8 --- /dev/null +++ b/docs/diagrams/deployment/DeploymentDiagramLevel1.puml @@ -0,0 +1,43 @@ +@startuml + +title WIQ Deployment View + +legend right + |Color| Type | + |<#darkseagreen>| Container | + |<#darkolivegreen>| WIQ Server | + |<#OliveDrab>| External Service | +end legend + +node "Server Hosting WIQ" #darkolivegreen { + node "KIWIQ Proxy" #darkseagreen + node "KIWIQ WebApp Server" #darkseagreen { + component "KIWIQ React Application" + } + node "KIWIQ API" #darkseagreen{ + component "KIWIQ_API.jar" + } + node "PostgreSQL Docker" #darkseagreen{ + database "KIWIQ Database" + } + node "Question generator" #darkseagreen{ + component "Question_Generator.jar" + } + node "Grafana" #darkseagreen + node "Prometheus" #darkseagreen +} +node "User Computer" #OliveDrab { + frame "Web Client" +} +node "WikiData Server" #OliveDrab { + frame "WikiData REST API" +} +"Web Client" ..> "KIWIQ Proxy" : "HTTPS" +"KIWIQ Proxy" ..> "KIWIQ React Application" +"KIWIQ React Application" ..> "KIWIQ_API.jar" : "HTTPS" +"KIWIQ_API.jar" ..> "KIWIQ Database" : "JPA" +"Question_Generator.jar" ..> "WikiData REST API" : "HTTPS, SPARQL" +"Question_Generator.jar" ..> "KIWIQ Database" : "JPA" +"Prometheus" ..> "KIWIQ_API.jar" : "Actuator" +"Grafana" ..> "Prometheus" +@enduml \ No newline at end of file diff --git a/docs/diagrams/deployment/DeploymentDiagramLevel2.puml b/docs/diagrams/deployment/DeploymentDiagramLevel2.puml new file mode 100644 index 00000000..fec796b2 --- /dev/null +++ b/docs/diagrams/deployment/DeploymentDiagramLevel2.puml @@ -0,0 +1,25 @@ +@startuml + +title KIWIQ API Deployment View + +legend right + |Color| Type | + |<#darkseagreen>| WIQ artifact | + |<#OliveDrab>| Package | +end legend + +node "KIWIQ_API.jar" #darkseagreen { + component "auth" #OliveDrab + component "commons"#OliveDrab + component "game" #OliveDrab + component "questions" #OliveDrab + component "statistics" #OliveDrab + +} +"auth" ..> "commons" +"game" ..> "commons" +"questions" ..> "commons" +"statistics" ..> "commons" +"game" ..> "questions" +"game" ..> "statistics" +@enduml \ No newline at end of file diff --git a/docs/diagrams/sequence/SequenceDiagramGame.puml b/docs/diagrams/sequence/SequenceDiagramGame.puml index 5b5a2c0a..1d66695c 100644 --- a/docs/diagrams/sequence/SequenceDiagramGame.puml +++ b/docs/diagrams/sequence/SequenceDiagramGame.puml @@ -1,34 +1,34 @@ @startuml Game's life cycle title Game Sequence Diagram -actor Client #darksalmon -participant API #darksalmon -database DB #salmon +actor Client #darkolivegreen +participant API #darkolivegreen +database DB #darkolivegreen skinparam Style strictuml skinparam SequenceMessageAlignment center Client -> API : start game -activate API #darksalmon +activate API #darkolivegreen API -> DB : store game info -activate DB #salmon +activate DB #darkolivegreen DB --> API : game info stored deactivate DB API --> Client : return game info deactivate API -loop #PeachPuff Round +loop #darkseagreen Round Client -> API : start round - activate API #darksalmon + activate API #darkolivegreen API -> DB : ask for question - activate DB #salmon + activate DB #darkolivegreen DB --> API : return question deactivate DB API --> Client : return question with all answers deactivate API Client -> API : send chosen answer - activate API #darksalmon + activate API #darkolivegreen API -> API : check answer is correct API -> DB : update game info - activate DB #salmon + activate DB #darkolivegreen DB --> API : game info updated deactivate DB API --> Client : inform user if guessed right @@ -37,7 +37,7 @@ loop #PeachPuff Round end loop One question API -> DB : [if last round] update ranking -activate DB #salmon +activate DB #darkolivegreen DB --> API : ranking updated deactivate DB API --> Client : inform user if guessed right diff --git a/docs/diagrams/sequence/SequenceDiagramLogIn.puml b/docs/diagrams/sequence/SequenceDiagramLogIn.puml index a30ad948..0b10edc6 100644 --- a/docs/diagrams/sequence/SequenceDiagramLogIn.puml +++ b/docs/diagrams/sequence/SequenceDiagramLogIn.puml @@ -1,30 +1,30 @@ @startuml login title Login Sequence Diagram -actor Client #darksalmon -participant API #darksalmon -database DB #salmon +actor Client #darkolivegreen +participant API #darkolivegreen +database DB #darkolivegreen skinparam Style strictuml skinparam SequenceMessageAlignment center Client -> API : enters credentials -activate API #darksalmon +activate API #darkolivegreen API -> DB : check credentials correct -alt #PeachPuff credentials correct - activate DB #salmon +alt #darkseagreen credentials correct + activate DB #darkolivegreen DB --> API : returns result deactivate DB API -> API : generate jwt and refresh tokens API -> DB : save tokens - activate DB #salmon + activate DB #darkolivegreen DB --> API : saves tokens deactivate DB API --> Client : return jwt dto deactivate API else credentials incorrect - activate DB #salmon + activate DB #darkolivegreen DB --> API : returns error deactivate DB - activate API #darksalmon + activate API #darkolivegreen API --> Client : return 403 error deactivate API end diff --git a/docs/diagrams/sequence/SequenceDiagramQuestionGeneration.puml b/docs/diagrams/sequence/SequenceDiagramQuestionGeneration.puml index fd7e49a5..8426374a 100644 --- a/docs/diagrams/sequence/SequenceDiagramQuestionGeneration.puml +++ b/docs/diagrams/sequence/SequenceDiagramQuestionGeneration.puml @@ -1,20 +1,20 @@ @startuml question generator title Question Generator Sequence Diagram -participant QuestionGenerator #darksalmon -participant WikiDataQS #darksalmon -database DB #salmon +participant QuestionGenerator #darkolivegreen +participant WikiDataQS #darkolivegreen +database DB #darkolivegreen skinparam Style strictuml skinparam SequenceMessageAlignment center -loop #PeachPuff Generate question templates -activate QuestionGenerator #darksalmon +loop #darkseagreen Generate question templates +activate QuestionGenerator #darkolivegreen QuestionGenerator -> WikiDataQS : request query template -activate WikiDataQS #darksalmon +activate WikiDataQS #darkolivegreen QuestionGenerator <-- WikiDataQS : returns query answers deactivate WikiDataQS QuestionGenerator -> QuestionGenerator : process query answer QuestionGenerator -> DB : store answers -activate DB #salmon +activate DB #darkolivegreen QuestionGenerator -> DB : store questions DB --> QuestionGenerator : info saved deactivate DB diff --git a/docs/diagrams/sequence/SequenceDiagramSignUp.puml b/docs/diagrams/sequence/SequenceDiagramSignUp.puml index 8d9fe1e2..8ba91312 100644 --- a/docs/diagrams/sequence/SequenceDiagramSignUp.puml +++ b/docs/diagrams/sequence/SequenceDiagramSignUp.puml @@ -1,31 +1,31 @@ @startuml sign up title Sign Up Sequence Diagram -actor Client #darksalmon -participant API #darksalmon -database DB #salmon +actor Client #darkolivegreen +participant API #darkolivegreen +database DB #darkolivegreen skinparam Style strictuml skinparam SequenceMessageAlignment center Client -> API : account details -activate API #darksalmon +activate API #darkolivegreen API -> API : validate details API -> DB : check email is unused -alt #PeachPuff email is unused - activate DB #salmon +alt #darkseagreen email is unused + activate DB #darkolivegreen DB --> API : email is unused deactivate DB API -> DB : register user - activate DB #salmon + activate DB #darkolivegreen DB --> API : user registered deactivate DB API --> Client : return confirmation deactivate API else email is used - activate DB #salmon + activate DB #darkolivegreen DB --> API : email is used deactivate DB - activate API #darksalmon + activate API #darkolivegreen API --> Client : 400 error deactivate API end diff --git a/docs/diagrams/uml/ConceptsDomainModel.puml b/docs/diagrams/uml/ConceptsDomainModel.puml new file mode 100644 index 00000000..63449912 --- /dev/null +++ b/docs/diagrams/uml/ConceptsDomainModel.puml @@ -0,0 +1,95 @@ +@startuml +enum QuestionCategory { + GEOGRAPHY + SPORTS + MUSIC + ART + VIDEOGAMES +} + +enum AnswerCategory { + CAPITAL_CITY + COUNTRY + SONG + STADIUM + BALLON_DOR + GAMES_PUBLISHER + PAINTING + WTPOKEMON + GAMES_COUNTRY + GAMES_GENRE + BASKETBALL_VENUE + COUNTRY_FLAG +} + +enum QuestionType { + TEXT + IMAGE +} + +enum GameMode { + KIWI_QUEST + FOOTBALL_SHOWDOWN + GEO_GENIUS + VIDEOGAME_ADVENTURE + ANCIENT_ODYSSEY + RANDOM + CUSTOM +} + +class Question { + content: String + answers: List + correctAnswer: Answer + questionCategory: QuestionCategory + type: QuestionType + games: List +} + +class User { + username: String + email: String + password: String + role: String + games: List + statistics: Statistics +} + +class Statistics { + correct: Long + wrong: Long + total: Long + user: User +} + +class Answer { + text: String + category: AnswerCategory + language: String +} + +class Game { + rounds: long + actualRound: long + user: User + questions: List + correctlyAnsweredQuestions: int + language: String + roundStartTime: LocalDateTime + roundDuration: Integer + currentQuestionAnswered: boolean + isGameOver: boolean + gamemode: GameMode + questionCategoriesForCustom: List +} + + +User "1"--"1" Statistics +Game "n"--"n" Question +Game "n" -- "1" User +Question "n" -- "n" Answer +GameMode -- Game +Question -- QuestionCategory +Answer -- AnswerCategory +Question -- QuestionType +@enduml \ No newline at end of file diff --git a/docs/src/01_introduction_and_goals.adoc b/docs/src/01_introduction_and_goals.adoc index d3a42dfb..aa8975c0 100644 --- a/docs/src/01_introduction_and_goals.adoc +++ b/docs/src/01_introduction_and_goals.adoc @@ -2,19 +2,18 @@ ifndef::imagesdir[:imagesdir: ../images] [[section-introduction-and-goals]] == Introduction and Goals -RTVE has hired the company HappySw, composed of students from the Oviedo School of Software Engineering, to develop a new experimental version of the quiz show Saber y Ganar. This application will be called KiWiq, where users will be able to register and log in to play. The application will consist of answering questions of different types generated with Wikidata. For each question answered correctly, points will be obtained. +RTVE has hired the company HappySw, composed of students from the Oviedo School of Software Engineering, to develop a new game-show like web application. This application will be called KiWiq, where users will be able to register and log in to play. The application will consist of answering questions of different types generated with Wikidata. Questions answered correctly will count towards statistics that are displayed in a ranking. === Requirements Overview * The system shall provide non-registered users with the option to sign up. * The system shall provide unidentified users with the option to log in. * The system shall only be used by registered users. -* The system shall have a game mode with 9 rounds. -* In each round, the system shall generate a question. -* In each round, the system shall generate four answers, with only one being correct. +* The system shall have a game mode with a 9 rounds. +* In each round, the system shall fetch and display a question. +* In each round, the system shall display four answers, with only one being correct. * The system shall offer registered users access to the number of games they have played. * The system shall offer registered users access the number of questions they have answered correctly. * The system shall offer registered users access the number of questions they have answered incorrectly. -* The system shall offer registered users access the time they have spent within the system. * The system shall offer registered users access the ranking of the game. * The system shall set a time limit for registered users to respond to each question. @@ -39,7 +38,7 @@ See the complete functional requirements in the xref:#section-annex[Annex] of th [options="header",cols="1,2"] |=== |Role/Name|Expectations -| RTVE | To have a new experimental version of the Saber y Ganar quiz show. +| RTVE | To have a new application for a quiz game. | HappySw | Develop a good application that fulfills the requirements expected by the client. | Registered user | To play with an entertaining and easy-to-use application. An application with which the user learn about different topics. | Wikidata | Being able to offer service allowing people to use the data through the API. diff --git a/docs/src/02_architecture_constraints.adoc b/docs/src/02_architecture_constraints.adoc index 3b28b338..1fad8854 100644 --- a/docs/src/02_architecture_constraints.adoc +++ b/docs/src/02_architecture_constraints.adoc @@ -3,7 +3,7 @@ ifndef::imagesdir[:imagesdir: ../images] [[section-architecture-constraints]] == Architecture Constraints -The application must be developed according to some constraints that were defined by the professors. These constraints are meant to be the cornerstones of our project as they are mandatory and provide a baseline to work on. The following tables will define the constraints. +The application must be developed according to some constraints that were defined by the client. These constraints are meant to be the cornerstones of our project as they are mandatory and provide a baseline to work on. The following tables will define the constraints. *Technical constraints* diff --git a/docs/src/03_system_scope_and_context.adoc b/docs/src/03_system_scope_and_context.adoc index 36fc857d..a9341dc8 100644 --- a/docs/src/03_system_scope_and_context.adoc +++ b/docs/src/03_system_scope_and_context.adoc @@ -3,16 +3,33 @@ ifndef::imagesdir[:imagesdir: ../images] == System Scope and Context === Business Context -[plantuml,"Business context diagram",png, align="center", title="Overall view of the business context"] +[plantuml,"C4 Level 1 - Business context diagram",png, align="center", title="Overall view of the business context"] ---- -include::../diagrams/BusinessContextDiagram.puml[] +include::../diagrams/c4/C4-Level1.puml[] ---- - -The WIQ application will communicate with the WikiData API through REST HTTP calls using SPARQL for the queries. It will ask the API for information that will later be used for generating the questions that will be shown to the player. This information will come in the form of text, images or audio. +The player interacts with the Kiwiq system, which will communicate with the WikiData API through REST HTTP calls using SPARQL for the queries. It will ask the API for information that will later be used for generating the questions that will be shown to the player. This information will come in the form of text or images. === Technical Context -image::TechnicalContextDiagram.png[align="center",title="Technical Context",link="TechnicalContextDiagram.png] -The WIQ application will be deployed together in the same server. The WIQ client will be deployed on a nginx web server. This client will communicate with the API through HTTPS REST calls and exchange information through JSON objects. The WIQ REST API will be run as a .jar file on the server and connect to a Database run on a postgresql docker container. The connection layer between the SpringBoot API and the database will be JPA. -The REST API will request information to the WikiData REST API through HTTPS calls passing a SPARQL query in order to retrieve data. +[plantuml,"C4 Level 2 - Container context diagram",png, align="center", title="Overall view of the technical context"] +---- +include::../diagrams/c4/C4-Level2.puml[] +---- +The Kiwiq system will be deployed together in the same server and contains different modules: + +* **Kiwiq Proxy: ** +When interacting with the server, an nginx proxy will be tasked with redirecting the queries to the petitions to the Kiwiq client will also be deployed on a nginx web server. + +* **Kiwiq Client: ** +This client will be served to the client and communicates with the API through HTTPS REST calls and exchanges information through JSON objects. The client will be developed in React and Javascript and is deployed via a nginx server. + +* **Kiwiq REST API:** +The Kiwiq REST API will be run as a .jar file on the server and connect to a database running on a PostgreSQL docker container. The connection layer between the SpringBoot API and the database will be JPA. + +* **Kiwiq database:** +In the database the questions and answers generated by the Question Generator module will be stored, written in Java and using JPA as a connection layer. The DBMS is PostgreSQL. + +* **Question generator:** +The Question Generator will also use the WikiData REST API to retrieve information to generate questions. It will generate the questions by connecting to the Wikidata REST API through HTTPs calls and passing a SPARQL query to retrieve the data that will later be used in the question generation. It is written in Java and uses JPA + diff --git a/docs/src/04_solution_strategy.adoc b/docs/src/04_solution_strategy.adoc index 7d189696..908bfb82 100644 --- a/docs/src/04_solution_strategy.adoc +++ b/docs/src/04_solution_strategy.adoc @@ -13,7 +13,7 @@ Regarding the technologies, we decided to use the following ones: ** As a consecuence of this, pure JavaScript is being used due to React 18 not supporting Typescript 5. - * **PostgreSQL** as DBMS to store the information. We nearly immediately discarded using MongoDB due to many of us not having experience with it, and those who did, preferred SQL. Many modern DBMS also include either JSON or JSONB data types, so using a DBMS whose main appeal is JSON and not many of us have experience with did not sit well with us. + * **PostgreSQL** as DBMS to store the information. We nearly immediately discarded using MongoDB due to many of us not having experience with it, and those who did, preferred relational databases. Many modern DBMS also include either JSON or JSONB data types, so using a DBMS whose main appeal is JSON and not many of us have experience with did not sit well with us. * **Java SpringBoot 3** for the backend/API, it being a language we are all comfortable with. The server will easily support multithreading if needed due to SpringBoot being an abstraction over servlets, something we would be able only to simulate if we used Node.js as it uses a single-threaded event loop. @@ -31,21 +31,69 @@ We also have a Whatsapp community for the team, and a Notion wiki. |=== |Quality attribute pursued|Solution chosen |Privacy|All stored password will be hashed, both client-side and server-side, to avoid password disclosure. The client-side password is also intended to prevent password discoverage in case it is a repeated one. -|Robustness|Currently, all validations will take place server-side to avoid not being properly taken care of due to JavaScript desactivation, such as when using the NoScript plug-in -|Availability|Since Wikidata has a 1 minute limit related to the API, the backend will start querying it upon start and fill the database with questions to increase speed and thus improve user experience| +|Robustness|Currently, all validations will take place server-side to avoid not being properly taken care of due to JavaScript desactivation, such as when using the NoScript plug-in or sending a request via cURL. +|Availability|Since Wikidata has a 1-minute limit related to the API, the backend will start querying it upon start and fill the database with questions to increase speed and thus improve user experience. This makes it so we are not dependent on the Wikidata API to be up for our system to work| |=== === Workflow +==== Team Workflow: We have divided ourselves in teams related to our own areas of expertise, but those divisions are indicative, and frontend teams may review or comment PRs if they wish, or vice versa. The frontend team may also ask input from the backend team if they wish, and the backend team may do the same. -All in all, we strive to achieve a very flexible workflow in which everyone's input may be considered if they wish to give it. +Separation of the group into teams though, tends to reflect on the final structure of the project, as stated in Conway's law. To prevent this, we employed the use of API definition tools such as Swagger to make the integration of frontend and backend not dependent on having members of both teams present. Conway's law still affected in other aspects, though. -=== Code Style +Meetings are also organized each week so as to keep the team updated, decide what should be worked on next and discuss any problems that may arise from implementation. -Regarding the code style, we must make two important distinctions: the frontend and backend. In the latter, we will mainly use Object Oriented Programming because our language of choice is Java, which strongly favours it. Regarding the former, it will be more of a case-by-case approach, as for instance, OOP-oriented React is deprecated in favor of a functional approach, but sometimes we may need OOP's strengths. +==== Coding workflow: +Pair programming was implemented in the backend team, which helped immensely to shorten the existing knowledge gaps and achieve a consistent coding style. This also reduced the number of PRs that needed to be validated, since having 2 people write the code increases its reliability. - * In the backend, the structure will be that of a typical Maven project. +==== Git workflow: +Trunk Based Development was used as source-control branching model, using develop as our trunk branch, and merging into master for tested releases. + +For commit messages we used the specification on https://www.conventionalcommits.org/en/v1.0.0/ so as to keep them consistent. + +For branch naming we used a variation of Conventional Commits commit naming, naming branches with its purpose first (docs,feat,fix...). + +Pull Requests were the main method of contributing to the project, these needing to be validated by at least 2 other teammates before merging to ensure code quality. + +=== Code Style/Structure + +Regarding the code style, we must make two important distinctions: the frontend and backend. In the latter, we will mainly use Object-Oriented Programming because our language of choice is Java, which strongly favours it. Regarding the former, it will be more of a case-by-case approach, as for instance, OOP-oriented React is deprecated in favor of a functional approach, but sometimes we may need OOP's strengths. + +==== Backend +===== API +In the backend, the structure will be that of a typical Maven project, using different packages for different modules of the project: + + * The `auth` package is used for *authentication* related endpoints and configuration. + * The `game` package is used for *game* related endpoints and logic + * The `questions` package is used for *question* related endpoints and logic + * The `statistics` package is used for *statistics* related endpoints and logic + * The `commons` package is used for common logic that may be used among different packages, such as *utils* classes or *user* logic. + +In each of this packages, the following structure is followed: + + * The `dtos` package stores *Data Transfer Objects*, used for sending or receiving data + * The `mappers` package stores classes used for mapping from *models* to *DTOs* or vice versa. + +In our Spring Boot project the following structure is found in each of our modules, following a Domain Driven Design approach: + + * A `Controller` handles the requests done to our API. + * A `Service` handles the retrieval of the *Models* from the database using *Repositories*. + * A `Model` is retrieved and handles its domain logic. + * A `Repository` is used for retrieving *Models* from the database. + +A crucial part of the design is that the models are the ones handling the logic, as described in Jimmy Bogard's talk: https://www.youtube.com/watch?v=UYmTUw5LXwQ + +In regard to testing, a Test First approach was employed when possible, and the logic of the *Models* and the *Services* was tested, as well as the responses given by the *Controllers* in different situations. + +===== Question Generator +In the question generator, the structure is simple, using three packages to structurize the code: + + * The `model` package is used to store the classes that model the questions and answers. + * The `repositories` package, where classes related to storing the questions and answers in the DB can be found. + * The `templates` package, where all the classes where the questions are created by using calls to wikidata can be found. + +==== Frontend * In the frontend, the structure will be quite different: ** The `src/components` will contain single components which we may reuse. ** The `src/pages` will contain the endpoints and will follow a simple structure. For instance, given a `/statistics/personal` and a `/statistics/general` endpoints, both will be independent React components that will return the page and be placed under the `src/pages/statistics` folder. diff --git a/docs/src/05_building_block_view.adoc b/docs/src/05_building_block_view.adoc index 147b29e1..3ac37f46 100644 --- a/docs/src/05_building_block_view.adoc +++ b/docs/src/05_building_block_view.adoc @@ -5,13 +5,12 @@ ifndef::imagesdir[:imagesdir: ../images] == Building Block View - -=== Whitebox Overall System +=== Whitebox Overall System (C4 Level 1) _**Overview Diagram**_ [plantuml,"Business context diagram",png, align="center", title="Overall view of the business context"] ---- -include::../diagrams/BusinessContextDiagram.puml[] +include::../diagrams/c4/C4-Level1.puml[] ---- Motivation:: @@ -21,31 +20,59 @@ Contained Building Blocks:: **** * **Player:** This is the user that will be playing with our application. They will need to be authenticated to be able to play. -* **WIQ Application:** This is the main application that will reproduce how the game will work. This part will be more detailed in the following parts. +* **Kiwiq Application:** This is the main application that will reproduce how the game will work. This part will be more detailed in the following parts. * **WikiData API:** This is an external API, which will provide us with the information to produce the questions. **** Important Interfaces:: -This part will be more detailed later, since the structure of the different interfaces/classes has not been discussed by the team yet. - +The user will interact with the system via the web client, which will allow them to play games. The system will then interact with the WikiData API via the question generator module by doing HTTPs requests with SPARQL queries in them. -=== Level 2 +=== Container Diagram (C4 Level 2) +[plantuml,"Container diagram",png, align="center", title="Overall view of the container context"] +---- +include::../diagrams/c4/C4-Level2.puml[] +---- Motivation:: -An inner view on the WIQ Application and its components inside. How the WIQ application will be structured inside and its main components. +An inner view on the Kiwiq Application and its components inside. How the Kiwiq application will be structured inside and its main components. Contained Building Blocks:: **** -* **WIQ Client:** This is the connection between the user and the application. It will allow the users to play the WIQ game. This part will be developed in React with Typescript for its clear component structure, simplified code quality and separation of concerns. -* **WIQ REST API:** This is the part responsible for managing the users that log into the application, managing also the logic of the game and sending the request to the Wikidata API for the question generation. This part is going to be developed in SpringBoot due to its foundations on the Java programming language, which is the language that the developers find the easiest to develop in. +* **Kiwiq Proxy: ** +When interacting with the server, an nginx proxy will be tasked with redirecting the queries to the petitions to the Kiwiq client will also be deployed on a nginx web server. + +* **Kiwiq Client:** This is the connection between the user and the application. It will allow the users to play the WIQ game. This part will be developed in React with Typescript for its clear component structure, simplified code quality and separation of concerns. +* **Kiwiq REST API:** This is the part responsible for managing the users that log into the application, managing also the logic of the game and sending the request to the Wikidata API for the question generation. This part is going to be developed in SpringBoot due to its foundations on the Java programming language, which is the language that the developers find the easiest to develop in. * **Question Generator Module:** This component is in charge of everything related with the questions. It retrieves the information from WikiData QS and stores it in the WIQ Database, which later is queried for questions and answers from the REST API. -* **WIQ Database:** This is where the most important data is going to be stored. Such as, users questions and other game info that will be specified in the future. The database we chose to use is PostgreSQL, since it is compatible with Docker and it's an object-relational kind of database, which is easier for the developers to use. Another alternative would've been to use MySQL. +* **Kiwiq Database:** This is where the most important data is going to be stored. Such as, users questions and other game info that will be specified in the future. The database we chose to use is PostgreSQL, since it is compatible with Docker and it's an object-relational kind of database, which is easier for the developers to use. Another alternative would've been to use MySQL. **** Important Interfaces:: -We are connecting the front end with the back end via REST API. Also, the Question Generator Module communicates with WikiData QS this way. -The Question Generator Module connects to the WIQ DataBase through JPA. -In the near future, we are planning on allowing HTTPS connections, so there would be a proxy server in between the user's agent and the back end. +We are connecting the front end with the back end via a REST API, using HTTPs requests. Also, the Question Generator Module communicates with WikiData QS this way. +The Question Generator Module connects to the WIQ DataBase through JPA, where it stores the questions that will later be used by the REST API. + +=== Component Diagram (C4 Level 3) +[plantuml,"Component diagram",png, align="center", title="Overall view of the component context"] +---- +include::../diagrams/c4/C4-Level3.puml[] +---- +Motivation:: +An inner view on the Kiwiq API and its components inside. How the Kiwiq API will be structured inside and its main components. + +Contained Components:: +**** +* **Authentication module:** +Tasked with handling of the login and register of the users as well as restricting the user access. +* **Game module:** +Tasked with handling the games allowing for creating new games, starting rounds, sending answers and updating statistics. +* **Question module:** +Tasked with handling the questions, allowing to get any question from the system, as well as retrieving them from the database. +* **Statistics module:** +Tasked with handling the statistics, allowing to check the top 10 users in the system, as well as saving the statistics. + +All the previously mentioned modules also use a common module named *commons*, that contains logic common to all of them, like the user handling or some util classes. +**** + diff --git a/docs/src/07_deployment_view.adoc b/docs/src/07_deployment_view.adoc index 703b45f0..d9398810 100644 --- a/docs/src/07_deployment_view.adoc +++ b/docs/src/07_deployment_view.adoc @@ -5,7 +5,7 @@ ifndef::imagesdir[:imagesdir: ../images] == Deployment View [plantuml,"Deployment diagram",png] ---- -include::../diagrams/deployment/DeploymentDiagram.puml[] +include::../diagrams/deployment/DeploymentDiagramLevel1.puml[] ---- === Infrastructure Level 1 @@ -21,10 +21,13 @@ As stated before, we consider the main advantage of this architecture the interc Mapping of Building Blocks to Infrastructure:: * The webapp/frontend/client is contained within the `webapp` subfolder. - * The API/backend is contained within the `api` subfolder. + * The API/backend is contained within the `quiz-api` subfolder. ** The database will be generated on deployment. ** Wikidata is an external component, so although it is an important part of the deployment architecture, it is something we do not have access to changing. + ** The grafana config is found within the `monitoring/grafana` subdirectory + ** The prometheus config is found within the `monitoring/prometheus` subdirectory * The question generator is a separate component that will be deployed on the server only at the beginning of the system. It is contained within the `questiongenerator` subfolder. + * The configuration for the proxy container is found within the `proxy_conf` subfolder. === Infrastructure Level 2 @@ -33,14 +36,17 @@ Mapping of Building Blocks to Infrastructure:: This component is self-contained and does not require much explanation. ==== API/Backend - +[plantuml,"API Deployment diagram",png] +---- +include::../diagrams/deployment/DeploymentDiagramLevel2.puml[] +---- ===== Server -Our main idea is that the server will be a self-contained .jar file with all the dependencies required within. It will communicate with the database and periodically query Wikidata to generate questions until a certain number has been obtained once per minute to fill up the database and improve speed. +Our main idea is that the server will be a self-contained .jar file with all the dependencies required within. It will communicate with the database to retrieve the questions. ===== Database -The database will contain the data used by the system. Therefore, it will contain user data, as well as the data related to the questions and their answers. The databases to store the questions (and therefore the answers) and the user data might be different, though. +The database will contain the data used by the system. Therefore, it will contain user data, as well as the data related to the questions and their answers. ===== Question Generator The question generator will be run only at the beginning of the application. It will connect with Wikidata using SPARQL to generate questions and answers and store them in the database. This question generation will generate all the questions used by the application at once. It could be run again to generate new questions if they are added. diff --git a/docs/src/08_concepts.adoc b/docs/src/08_concepts.adoc index 4d2e9248..7ccdd2e3 100644 --- a/docs/src/08_concepts.adoc +++ b/docs/src/08_concepts.adoc @@ -4,90 +4,25 @@ ifndef::imagesdir[:imagesdir: ../images] == Cross-cutting Concepts .Domain Model -This is the first version of the diagram, it will be updated if needed. +This is the diagram that includes the domain model of the backend. -[plantuml,"ConceptsDomainModel1",png] +[plantuml,"Concept Domain Model",png] ---- -@startuml -enum QuestionCategory { - GEOGRAPHY - SPORTS - MUSIC -} - -enum AnswerCategory { - CAPITAL_CITY - COUNTRY - SONG - STADIUM - BALLON_DOR -} - -enum QuestionType{ - TEXT - IMAGE - AUDIO -} - -class Question{ - content: String - answers: List - correctAnswer: Answer - questionCategory: QuestionCategory - type: QuestionType - games: List -} - -class User{ - username: String - email: String - password: String - role: String - games: List -} - -class Statistics{ - correct: Long - wrong: Long - total: Long - user: User -} - -class Answer { - text: String - category: AnswerCategory - language: String -} - -class Game { - user: User - questions: List - rounds: int - actualRound: int - correctlyAnsweredQuestions: int - language: String - roundStartTime: LocalDateTime - roundDuration: Integer - currentQuestionAnswered: boolean - isGameOver: boolean -} - - -User "1"--"1" Statistics -Game "n"--"n" Question -Game "n" -- "1" User -Question "n" -- "n" Answer - -@enduml +include::../diagrams/uml/ConceptsDomainModel.puml[] ---- |=== -| Class | Explanation -| Question | The model of the questions, has a type to specify if it is text, image or audio. Stores both right and wrong answers +| *Class* | *Explanation* +| Question | The model of the questions, has a type to specify if it is text or image. Stores both right and wrong answers | User | The people using the application, they have statistics and take part in a ranking to compete | Answer | Models each possible answer, created to reuse answers that are common to different questions, as well as distractors | Game | It is created when the user starts a game and includes the rounds that the user has to answer | Statistics | Stores information about the amount of correct and wrong answers that each user has answered +| *Enum* | *Explanation* +| QuestionCategory | Category for the question +| QuestionType | Type of the question (if it shows a text or an image etc) +| AnswerCategory | Category of the answer (used also for getting distractors) +| GameMode | Game mode for the game |=== .Question Generator diff --git a/questiongenerator/src/main/java/templates/VideogamesGenreQuestion.java b/questiongenerator/src/main/java/templates/VideogamesGenreQuestion.java index 50c489e8..b0cc589a 100644 --- a/questiongenerator/src/main/java/templates/VideogamesGenreQuestion.java +++ b/questiongenerator/src/main/java/templates/VideogamesGenreQuestion.java @@ -28,7 +28,7 @@ public void setQuery() { " OPTIONAL { " + " ?game wdt:P136 ?genreItem. " + " ?genreItem rdfs:label ?genreLabel. " + - " FILTER(LANG(?genreLabel) IN (\"en\", \"es\")) " + + " FILTER(LANG(?genreLabel) IN (\"" + langCode + "\")) " + " } " + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"" + langCode + "\". } " + "} " +