From f483f14a61ff5a8af1330cabb02ce1c6bc39d3df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:48:24 +0200 Subject: [PATCH 01/59] New geography question template: Area --- .../geography/AreaQuestionGenerator.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java new file mode 100644 index 00000000..d69d2edd --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java @@ -0,0 +1,52 @@ +package com.uniovi.components.generators.geography; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + +public class AreaQuestionGenerator extends AbstractGeographyGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "What is the area of "); + put("es", "¿Cuál es el área de "); + put("fr", "Quelle est la superficie de "); + } + }; + + public AreaQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?country ?countryLabel ?area\n" + + "WHERE {" + + " ?country wdt:P31 wd:Q3624078 ." + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + + " ?country wdt:P2046 ?area ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + // Este generador de preguntas no necesita opciones, ya que la respuesta correcta es el área. + return Collections.emptyList(); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("area").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("countryLabel").path("value").asText() + "?"; + } +} From 9f26f042933a1c27faf2d0414f92db987d37247d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:48:55 +0200 Subject: [PATCH 02/59] New geography question template: Currency --- .../geography/CurrencyQuestionGenerator.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java new file mode 100644 index 00000000..14bda93f --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java @@ -0,0 +1,76 @@ +package com.uniovi.components.generators.geography; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + +public class CurrencyQuestionGenerator extends AbstractGeographyGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "What is the currency of "); + put("es", "¿Cuál es la moneda de "); + put("fr", "Quelle est la monnaie de "); + } + }; + + public CurrencyQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?country ?countryLabel ?currency ?currencyLabel\n" + + "WHERE {" + + " ?country wdt:P31 wd:Q3624078 ." + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + + " ?country wdt:P38 ?currency ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllCurrencies(JsonNode resultsNode, String correctCurrency) { + // Obtener todas las monedas del JSON (distintas a la moneda correcta) + List allCurrencies = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String currency = result.path("currencyLabel").path("value").asText(); + if (!currency.equals(correctCurrency)) { + allCurrencies.add(currency); + } + } + return allCurrencies; + } + + private List selectRandomIncorrectCurrencies(List allCurrencies, String correctCurrency, int count) { + List incorrectCurrencies = new ArrayList<>(); + while (incorrectCurrencies.size() < count && allCurrencies.size() > 0) { + int randomIndex = random.nextInt(allCurrencies.size()); + String selectedCurrency = allCurrencies.remove(randomIndex); + if (!selectedCurrency.equals(correctCurrency) && !incorrectCurrencies.contains(selectedCurrency)) { + incorrectCurrencies.add(selectedCurrency); + } + } + return incorrectCurrencies; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String currencyLabel = result.path("currencyLabel").path("value").asText(); + return selectRandomIncorrectCurrencies(getAllCurrencies(results, currencyLabel), currencyLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("currencyLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("countryLabel").path("value").asText() + "?"; + } +} From 6d1b749b0cfd3cc8a325b09be22a8c704f16813f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:51:36 +0200 Subject: [PATCH 03/59] New geography question template: Population --- .../geography/LanguageQuestionGenerator.java | 76 +++++++++++++++++++ .../PopulationQuestionGenerator.java | 52 +++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java new file mode 100644 index 00000000..b1bf363a --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java @@ -0,0 +1,76 @@ +package com.uniovi.components.generators.geography; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + +public class LanguageQuestionGenerator extends AbstractGeographyGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "What is the official language of "); + put("es", "¿Cuál es el idioma oficial de "); + put("fr", "Quelle est la langue officielle de "); + } + }; + + public LanguageQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?country ?countryLabel ?language ?languageLabel\n" + + "WHERE {" + + " ?country wdt:P31 wd:Q3624078 ." + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + + " ?country wdt:P37 ?language ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllLanguages(JsonNode resultsNode, String correctLanguage) { + // Obtener todos los idiomas del JSON (distintos al idioma correcto) + List allLanguages = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String language = result.path("languageLabel").path("value").asText(); + if (!language.equals(correctLanguage)) { + allLanguages.add(language); + } + } + return allLanguages; + } + + private List selectRandomIncorrectLanguages(List allLanguages, String correctLanguage, int count) { + List incorrectLanguages = new ArrayList<>(); + while (incorrectLanguages.size() < count && allLanguages.size() > 0) { + int randomIndex = random.nextInt(allLanguages.size()); + String selectedLanguage = allLanguages.remove(randomIndex); + if (!selectedLanguage.equals(correctLanguage) && !incorrectLanguages.contains(selectedLanguage)) { + incorrectLanguages.add(selectedLanguage); + } + } + return incorrectLanguages; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String languageLabel = result.path("languageLabel").path("value").asText(); + return selectRandomIncorrectLanguages(getAllLanguages(results, languageLabel), languageLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("languageLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("countryLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java new file mode 100644 index 00000000..e0df4901 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java @@ -0,0 +1,52 @@ +package com.uniovi.components.generators.geography; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; + +public class PopulationQuestionGenerator extends AbstractGeographyGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "What is the population of "); + put("es", "¿Cuál es la población de "); + put("fr", "Quelle est la population de "); + } + }; + + public PopulationQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?country ?countryLabel ?population\n" + + "WHERE {" + + " ?country wdt:P31 wd:Q3624078 ." + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + + " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + + " ?country wdt:P1082 ?population ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + // Este generador de preguntas no necesita opciones, ya que la respuesta correcta es la población. + return Collections.emptyList(); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("population").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("countryLabel").path("value").asText() + "?"; + } +} From 898364921af083607ab386f8e922a57d8ab3b5a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:53:44 +0200 Subject: [PATCH 04/59] New geography question category: History --- .../java/com/uniovi/services/impl/CategoryServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java index 636bffe5..53bd6936 100644 --- a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java @@ -40,7 +40,8 @@ public Category getCategoryByName(String name) { } private static final Map.Entry[] CATEGORIES = new AbstractMap.SimpleEntry[] { - new AbstractMap.SimpleEntry<>("Geography", "Questions about geography") + new AbstractMap.SimpleEntry<>("Geography", "Questions about geography"), + new AbstractMap.SimpleEntry<>("History", "Questions about history") }; @PostConstruct From 3f412859ac974c5974b88fb9425a6d501d39fa4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:54:21 +0200 Subject: [PATCH 05/59] Revert "New geography question category: History" This reverts commit 898364921af083607ab386f8e922a57d8ab3b5a7. --- .../java/com/uniovi/services/impl/CategoryServiceImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java index 53bd6936..636bffe5 100644 --- a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java @@ -40,8 +40,7 @@ public Category getCategoryByName(String name) { } private static final Map.Entry[] CATEGORIES = new AbstractMap.SimpleEntry[] { - new AbstractMap.SimpleEntry<>("Geography", "Questions about geography"), - new AbstractMap.SimpleEntry<>("History", "Questions about history") + new AbstractMap.SimpleEntry<>("Geography", "Questions about geography") }; @PostConstruct From 2888e2dc95a7cc08775239b48285831b08e1029d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:55:17 +0200 Subject: [PATCH 06/59] New history question template: Artifact --- .../history/AbstractHistoryGenerator.java | 17 +++++ .../HistoricalArtifactQuestionGeneration.java | 75 +++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java diff --git a/src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java b/src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java new file mode 100644 index 00000000..da8d870b --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java @@ -0,0 +1,17 @@ +package com.uniovi.components.generators.history; + +import com.uniovi.components.generators.AbstractQuestionGenerator; +import com.uniovi.entities.Category; +import com.uniovi.services.CategoryService; + +public abstract class AbstractHistoryGenerator extends AbstractQuestionGenerator { + + protected AbstractHistoryGenerator(CategoryService categoryService) { + super(categoryService); + } + + @Override + public Category getCategory() { + return categoryService.getCategoryByName("History"); + } +} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java new file mode 100644 index 00000000..0bb30abf --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.history; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.*; + +public class HistoricalArtifactQuestionGeneration extends AbstractHistoryGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which historical artifact is associated with "); + put("es", "¿Con qué artefacto histórico se asocia "); + put("fr", "Quel artefact historique est associé à "); + } + }; + + public HistoricalArtifactQuestionGeneration(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + private List getAllArtifacts(JsonNode resultsNode, String correctArtifact) { + // Obtaining all historical artifacts from the JSON (different from the correct artifact) + List allArtifacts = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String artifact = result.path("artifactLabel").path("value").asText(); + if (!artifact.equals(correctArtifact)) { + allArtifacts.add(artifact); + } + } + return allArtifacts; + } + + private List selectRandomIncorrectArtifacts(List allArtifacts, String correctArtifact, int count) { + List incorrectArtifacts = new ArrayList<>(); + while (incorrectArtifacts.size() < count && allArtifacts.size() > 0) { + int randomIndex = random.nextInt(allArtifacts.size()); + String selectedArtifact = allArtifacts.remove(randomIndex); + if (!selectedArtifact.equals(correctArtifact) && !incorrectArtifacts.contains(selectedArtifact)) { + incorrectArtifacts.add(selectedArtifact); + } + } + return incorrectArtifacts; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String artifactLabel = result.path("artifactLabel").path("value").asText(); + return selectRandomIncorrectArtifacts(getAllArtifacts(results, artifactLabel), artifactLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("artifactLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?artifact ?artifactLabel ?historicalEvent ?historicalEventLabel\n" + + "WHERE {" + + " ?artifact wdt:P31 wd:Q5314 ." + + " ?historicalEvent wdt:P31 wd:Q198 ." + + " OPTIONAL { ?artifact wdt:P1080 ?historicalEvent } ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}" + + "ORDER BY ?artifactLabel"; + } +} From 6d67b5e19338fd387b603bfd807bdb3c7138cb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:56:06 +0200 Subject: [PATCH 07/59] New history question template: Battle --- .../HistoricalBattleQuestionGeneration.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java new file mode 100644 index 00000000..5c83c79c --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.history; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.*; + +public class HistoricalBattleQuestionGeneration extends AbstractHistoryGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which historical battle is associated with "); + put("es", "¿Con qué batalla histórica se asocia "); + put("fr", "Quelle bataille historique est associée à "); + } + }; + + public HistoricalBattleQuestionGeneration(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + private List getAllBattles(JsonNode resultsNode, String correctBattle) { + // Obtaining all historical battles from the JSON (different from the correct battle) + List allBattles = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String battle = result.path("battleLabel").path("value").asText(); + if (!battle.equals(correctBattle)) { + allBattles.add(battle); + } + } + return allBattles; + } + + private List selectRandomIncorrectBattles(List allBattles, String correctBattle, int count) { + List incorrectBattles = new ArrayList<>(); + while (incorrectBattles.size() < count && allBattles.size() > 0) { + int randomIndex = random.nextInt(allBattles.size()); + String selectedBattle = allBattles.remove(randomIndex); + if (!selectedBattle.equals(correctBattle) && !incorrectBattles.contains(selectedBattle)) { + incorrectBattles.add(selectedBattle); + } + } + return incorrectBattles; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String battleLabel = result.path("battleLabel").path("value").asText(); + return selectRandomIncorrectBattles(getAllBattles(results, battleLabel), battleLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("battleLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?battle ?battleLabel ?historicalEvent ?historicalEventLabel\n" + + "WHERE {" + + " ?battle wdt:P31 wd:Q178561 ." + + " ?historicalEvent wdt:P31 wd:Q198 ." + + " OPTIONAL { ?battle wdt:P361 ?historicalEvent } ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}" + + "ORDER BY ?battleLabel"; + } +} From 760b15a608187a49ef4aa6e57a0d27870b0e0bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:56:32 +0200 Subject: [PATCH 08/59] New history question template: Dynasty --- .../HistoricalDynastyQuestionGeneration.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java new file mode 100644 index 00000000..7f65f88e --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.history; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.*; + +public class HistoricalDynastyQuestionGeneration extends AbstractHistoryGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which historical dynasty is associated with "); + put("es", "¿Con qué dinastía histórica se asocia "); + put("fr", "Quelle dynastie historique est associée à "); + } + }; + + public HistoricalDynastyQuestionGeneration(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + private List getAllDynasties(JsonNode resultsNode, String correctDynasty) { + // Obtaining all historical dynasties from the JSON (different from the correct dynasty) + List allDynasties = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String dynasty = result.path("dynastyLabel").path("value").asText(); + if (!dynasty.equals(correctDynasty)) { + allDynasties.add(dynasty); + } + } + return allDynasties; + } + + private List selectRandomIncorrectDynasties(List allDynasties, String correctDynasty, int count) { + List incorrectDynasties = new ArrayList<>(); + while (incorrectDynasties.size() < count && allDynasties.size() > 0) { + int randomIndex = random.nextInt(allDynasties.size()); + String selectedDynasty = allDynasties.remove(randomIndex); + if (!selectedDynasty.equals(correctDynasty) && !incorrectDynasties.contains(selectedDynasty)) { + incorrectDynasties.add(selectedDynasty); + } + } + return incorrectDynasties; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String dynastyLabel = result.path("dynastyLabel").path("value").asText(); + return selectRandomIncorrectDynasties(getAllDynasties(results, dynastyLabel), dynastyLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("dynastyLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?dynasty ?dynastyLabel ?historicalEvent ?historicalEventLabel\n" + + "WHERE {" + + " ?dynasty wdt:P31 wd:Q11410 ." + + " ?historicalEvent wdt:P31 wd:Q198 ." + + " OPTIONAL { ?dynasty wdt:P108 ?historicalEvent } ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}" + + "ORDER BY ?dynastyLabel"; + } +} From 53c1dff15626483dae977902841279362f3f2a84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:56:55 +0200 Subject: [PATCH 09/59] New history question template: Event --- .../HistoricalEventQuestionGeneration.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java new file mode 100644 index 00000000..cede3058 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.history; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.*; + +public class HistoricalEventQuestionGeneration extends AbstractHistoryGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "In what historical event did "); + put("es", "¿En qué evento histórico participó "); + put("fr", "Dans quel événement historique a participé "); + } + }; + + public HistoricalEventQuestionGeneration(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + private List getAllEvents(JsonNode resultsNode, String correctEvent) { + // Obtener todos los eventos históricos del JSON (diferentes al evento correcto) + List allEvents = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String event = result.path("eventLabel").path("value").asText(); + if (!event.equals(correctEvent)) { + allEvents.add(event); + } + } + return allEvents; + } + + private List selectRandomIncorrectEvents(List allEvents, String correctEvent, int count) { + List incorrectEvents = new ArrayList<>(); + while (incorrectEvents.size() < count && allEvents.size() > 0) { + int randomIndex = random.nextInt(allEvents.size()); + String selectedEvent = allEvents.remove(randomIndex); + if (!selectedEvent.equals(correctEvent) && !incorrectEvents.contains(selectedEvent)) { + incorrectEvents.add(selectedEvent); + } + } + return incorrectEvents; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String eventLabel = result.path("eventLabel").path("value").asText(); + return selectRandomIncorrectEvents(getAllEvents(results, eventLabel), eventLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("eventLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("personLabel").path("value").asText() + "?"; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?person ?personLabel ?event ?eventLabel\n" + + "WHERE {" + + " ?person wdt:P31 wd:Q5 ." + + " ?event wdt:P31 wd:Q198 ." + + " OPTIONAL { ?person wdt:P106 ?event } ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}" + + "ORDER BY ?personLabel"; + } +} From d559d2a26ceac010bdd38f2cec0554c86d3639d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:57:08 +0200 Subject: [PATCH 10/59] New history question template: Invention --- ...HistoricalInventionQuestionGeneration.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java new file mode 100644 index 00000000..01af421d --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.history; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.*; + +public class HistoricalInventionQuestionGeneration extends AbstractHistoryGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which historical invention is associated with "); + put("es", "¿Con qué invención histórica se asocia "); + put("fr", "Quelle invention historique est associée à "); + } + }; + + public HistoricalInventionQuestionGeneration(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + private List getAllInventions(JsonNode resultsNode, String correctInvention) { + // Obtaining all historical inventions from the JSON (different from the correct invention) + List allInventions = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String invention = result.path("inventionLabel").path("value").asText(); + if (!invention.equals(correctInvention)) { + allInventions.add(invention); + } + } + return allInventions; + } + + private List selectRandomIncorrectInventions(List allInventions, String correctInvention, int count) { + List incorrectInventions = new ArrayList<>(); + while (incorrectInventions.size() < count && allInventions.size() > 0) { + int randomIndex = random.nextInt(allInventions.size()); + String selectedInvention = allInventions.remove(randomIndex); + if (!selectedInvention.equals(correctInvention) && !incorrectInventions.contains(selectedInvention)) { + incorrectInventions.add(selectedInvention); + } + } + return incorrectInventions; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String inventionLabel = result.path("inventionLabel").path("value").asText(); + return selectRandomIncorrectInventions(getAllInventions(results, inventionLabel), inventionLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("inventionLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?invention ?inventionLabel ?historicalEvent ?historicalEventLabel\n" + + "WHERE {" + + " ?invention wdt:P31 wd:Q39614 ." + + " ?historicalEvent wdt:P31 wd:Q198 ." + + " OPTIONAL { ?invention wdt:P921 ?historicalEvent } ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}" + + "ORDER BY ?inventionLabel"; + } +} From 277b86216a8746f403c234353c0edfc5cb1fc016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:57:26 +0200 Subject: [PATCH 11/59] New history question template: Leader --- .../HistoricalLeaderQuestionGeneration.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java new file mode 100644 index 00000000..17cce194 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.history; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.*; + +public class HistoricalLeaderQuestionGeneration extends AbstractHistoryGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which historical leader is associated with "); + put("es", "¿Con qué líder histórico se asocia "); + put("fr", "Quel leader historique est associé à "); + } + }; + + public HistoricalLeaderQuestionGeneration(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + private List getAllLeaders(JsonNode resultsNode, String correctLeader) { + // Obtaining all historical leaders from the JSON (different from the correct leader) + List allLeaders = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String leader = result.path("leaderLabel").path("value").asText(); + if (!leader.equals(correctLeader)) { + allLeaders.add(leader); + } + } + return allLeaders; + } + + private List selectRandomIncorrectLeaders(List allLeaders, String correctLeader, int count) { + List incorrectLeaders = new ArrayList<>(); + while (incorrectLeaders.size() < count && allLeaders.size() > 0) { + int randomIndex = random.nextInt(allLeaders.size()); + String selectedLeader = allLeaders.remove(randomIndex); + if (!selectedLeader.equals(correctLeader) && !incorrectLeaders.contains(selectedLeader)) { + incorrectLeaders.add(selectedLeader); + } + } + return incorrectLeaders; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String leaderLabel = result.path("leaderLabel").path("value").asText(); + return selectRandomIncorrectLeaders(getAllLeaders(results, leaderLabel), leaderLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("leaderLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?leader ?leaderLabel ?historicalEvent ?historicalEventLabel\n" + + "WHERE {" + + " ?leader wdt:P31 wd:Q5 ." + + " ?historicalEvent wdt:P31 wd:Q198 ." + + " OPTIONAL { ?leader wdt:P6 ?historicalEvent } ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}" + + "ORDER BY ?leaderLabel"; + } +} From 983432a8fd36da46837abd59c7364cf6e60e74b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:57:45 +0200 Subject: [PATCH 12/59] New history question template: Period --- .../HistoricalPeriodQuestionGeneration.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java new file mode 100644 index 00000000..b1a7f81c --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.history; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.scheduling.annotation.Scheduled; + +import java.util.*; + +public class HistoricalPeriodQuestionGeneration extends AbstractHistoryGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which historical period is associated with "); + put("es", "¿Con qué período histórico se asocia "); + put("fr", "Quelle période historique est associée à "); + } + }; + + public HistoricalPeriodQuestionGeneration(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + private List getAllPeriods(JsonNode resultsNode, String correctPeriod) { + // Obtaining all historical periods from the JSON (different from the correct period) + List allPeriods = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String period = result.path("periodLabel").path("value").asText(); + if (!period.equals(correctPeriod)) { + allPeriods.add(period); + } + } + return allPeriods; + } + + private List selectRandomIncorrectPeriods(List allPeriods, String correctPeriod, int count) { + List incorrectPeriods = new ArrayList<>(); + while (incorrectPeriods.size() < count && allPeriods.size() > 0) { + int randomIndex = random.nextInt(allPeriods.size()); + String selectedPeriod = allPeriods.remove(randomIndex); + if (!selectedPeriod.equals(correctPeriod) && !incorrectPeriods.contains(selectedPeriod)) { + incorrectPeriods.add(selectedPeriod); + } + } + return incorrectPeriods; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String periodLabel = result.path("periodLabel").path("value").asText(); + return selectRandomIncorrectPeriods(getAllPeriods(results, periodLabel), periodLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("periodLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?period ?periodLabel ?historicalEvent ?historicalEventLabel\n" + + "WHERE {" + + " ?period wdt:P31 wd:Q186067 ." + + " ?historicalEvent wdt:P31 wd:Q198 ." + + " OPTIONAL { ?period wdt:P155 ?historicalEvent } ." + + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}" + + "ORDER BY ?periodLabel"; + } +} From 4ccf34844a637cca296a0b262dc1d184533ccace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Sat, 6 Apr 2024 22:58:31 +0200 Subject: [PATCH 13/59] InsertSampleDataService updated with new question templates --- .../services/InsertSampleDataService.java | 86 +++++++++++++++---- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/uniovi/services/InsertSampleDataService.java b/src/main/java/com/uniovi/services/InsertSampleDataService.java index cfab4b6d..add55fcf 100644 --- a/src/main/java/com/uniovi/services/InsertSampleDataService.java +++ b/src/main/java/com/uniovi/services/InsertSampleDataService.java @@ -2,9 +2,8 @@ import com.uniovi.components.MultipleQuestionGenerator; import com.uniovi.components.generators.QuestionGenerator; -import com.uniovi.components.generators.geography.BorderQuestionGenerator; -import com.uniovi.components.generators.geography.CapitalQuestionGenerator; -import com.uniovi.components.generators.geography.ContinentQuestionGeneration; +import com.uniovi.components.generators.geography.*; +import com.uniovi.components.generators.history.*; import com.uniovi.dto.PlayerDto; import com.uniovi.entities.Associations; import com.uniovi.entities.GameSession; @@ -14,6 +13,7 @@ import com.uniovi.repositories.QuestionRepository; import jakarta.annotation.PostConstruct; import jakarta.transaction.Transactional; +import org.hibernate.validator.constraints.Currency; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -69,33 +69,87 @@ public void insertSampleQuestions() { @Transactional public void generateSampleData() { - questionRepository.deleteAll(); - MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( + // Generar preguntas de geografía en inglés + MultipleQuestionGenerator geographyQuestionsEn = new MultipleQuestionGenerator( new ContinentQuestionGeneration(categoryService, Question.ENGLISH), new CapitalQuestionGenerator(categoryService, Question.ENGLISH), - new BorderQuestionGenerator(categoryService, Question.ENGLISH) + new BorderQuestionGenerator(categoryService, Question.ENGLISH), + new AreaQuestionGenerator(categoryService, Question.ENGLISH), + new CurrencyQuestionGenerator(categoryService, Question.ENGLISH), + new LanguageQuestionGenerator(categoryService, Question.ENGLISH), + new PopulationQuestionGenerator(categoryService, Question.ENGLISH) ); - List questionsEn = allQuestionGenerator.getQuestions(); - questionsEn.forEach(questionService::addNewQuestion); + List geographyQuestions = geographyQuestionsEn.getQuestions(); + geographyQuestions.forEach(questionService::addNewQuestion); - allQuestionGenerator = new MultipleQuestionGenerator( + // Generar preguntas de geografía en español + MultipleQuestionGenerator geographyQuestionsEs = new MultipleQuestionGenerator( new ContinentQuestionGeneration(categoryService, Question.SPANISH), new CapitalQuestionGenerator(categoryService, Question.SPANISH), - new BorderQuestionGenerator(categoryService, Question.SPANISH) + new BorderQuestionGenerator(categoryService, Question.SPANISH), + new AreaQuestionGenerator(categoryService, Question.SPANISH), + new CurrencyQuestionGenerator(categoryService, Question.SPANISH), + new LanguageQuestionGenerator(categoryService, Question.SPANISH), + new PopulationQuestionGenerator(categoryService, Question.SPANISH) ); - List questionsEs = allQuestionGenerator.getQuestions(); - questionsEs.forEach(questionService::addNewQuestion); + List geographyQuestionsSpanish = geographyQuestionsEs.getQuestions(); + geographyQuestionsSpanish.forEach(questionService::addNewQuestion); - allQuestionGenerator = new MultipleQuestionGenerator( + // Generar preguntas de geografía en francés + MultipleQuestionGenerator geographyQuestionsFr = new MultipleQuestionGenerator( new ContinentQuestionGeneration(categoryService, Question.FRENCH), new CapitalQuestionGenerator(categoryService, Question.FRENCH), - new BorderQuestionGenerator(categoryService, Question.FRENCH) + new BorderQuestionGenerator(categoryService, Question.FRENCH), + new AreaQuestionGenerator(categoryService, Question.FRENCH), + new CurrencyQuestionGenerator(categoryService, Question.FRENCH), + new LanguageQuestionGenerator(categoryService, Question.FRENCH), + new PopulationQuestionGenerator(categoryService, Question.FRENCH) + ); + List geographyQuestionsFrench = geographyQuestionsFr.getQuestions(); + geographyQuestionsFrench.forEach(questionService::addNewQuestion); + + // Generar preguntas de historia en inglés + MultipleQuestionGenerator historyQuestionsEn = new MultipleQuestionGenerator( + new HistoricalArtifactQuestionGeneration(categoryService, Question.ENGLISH), + new HistoricalBattleQuestionGeneration(categoryService, Question.ENGLISH), + new HistoricalDynastyQuestionGeneration(categoryService, Question.ENGLISH), + new HistoricalEventQuestionGeneration(categoryService, Question.ENGLISH), + new HistoricalInventionQuestionGeneration(categoryService, Question.ENGLISH), + new HistoricalPeriodQuestionGeneration(categoryService, Question.ENGLISH), + new HistoricalLeaderQuestionGeneration(categoryService, Question.ENGLISH) + ); + List historyQuestions = historyQuestionsEn.getQuestions(); + historyQuestions.forEach(questionService::addNewQuestion); + + // Generar preguntas de historia en español + MultipleQuestionGenerator historyQuestionsEs = new MultipleQuestionGenerator( + new HistoricalArtifactQuestionGeneration(categoryService, Question.SPANISH), + new HistoricalBattleQuestionGeneration(categoryService, Question.SPANISH), + new HistoricalDynastyQuestionGeneration(categoryService, Question.SPANISH), + new HistoricalEventQuestionGeneration(categoryService, Question.SPANISH), + new HistoricalInventionQuestionGeneration(categoryService, Question.SPANISH), + new HistoricalPeriodQuestionGeneration(categoryService, Question.SPANISH), + new HistoricalLeaderQuestionGeneration(categoryService, Question.SPANISH) + ); + List historyQuestionsSpanish = historyQuestionsEs.getQuestions(); + historyQuestionsSpanish.forEach(questionService::addNewQuestion); + + // Generar preguntas de historia en francés + MultipleQuestionGenerator historyQuestionsFr = new MultipleQuestionGenerator( + new HistoricalArtifactQuestionGeneration(categoryService, Question.FRENCH), + new HistoricalBattleQuestionGeneration(categoryService, Question.FRENCH), + new HistoricalDynastyQuestionGeneration(categoryService, Question.FRENCH), + new HistoricalEventQuestionGeneration(categoryService, Question.FRENCH), + new HistoricalInventionQuestionGeneration(categoryService, Question.FRENCH), + new HistoricalPeriodQuestionGeneration(categoryService, Question.FRENCH), + new HistoricalLeaderQuestionGeneration(categoryService, Question.FRENCH) ); - List questionsFr = allQuestionGenerator.getQuestions(); - questionsFr.forEach(questionService::addNewQuestion); + List historyQuestionsFrench = historyQuestionsFr.getQuestions(); + historyQuestionsFrench.forEach(questionService::addNewQuestion); log.info("Sample questions inserted"); } + } From 5b978a5df1f82a56bc2b5d264f4dea822b7d8833 Mon Sep 17 00:00:00 2001 From: RicardoDiNu Date: Sat, 6 Apr 2024 23:21:57 +0200 Subject: [PATCH 14/59] Fix - Add new question category: History --- .../java/com/uniovi/services/impl/CategoryServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java index 636bffe5..53bd6936 100644 --- a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java @@ -40,7 +40,8 @@ public Category getCategoryByName(String name) { } private static final Map.Entry[] CATEGORIES = new AbstractMap.SimpleEntry[] { - new AbstractMap.SimpleEntry<>("Geography", "Questions about geography") + new AbstractMap.SimpleEntry<>("Geography", "Questions about geography"), + new AbstractMap.SimpleEntry<>("History", "Questions about history") }; @PostConstruct From 79cbfb5de46deeb2bc136645bc1dbc53c330b6b8 Mon Sep 17 00:00:00 2001 From: RicardoDiNu Date: Sat, 6 Apr 2024 23:46:19 +0200 Subject: [PATCH 15/59] Add new question category and templates: Science --- .../science/AbstractScienceGenerator.java | 17 +++++ .../MathPhysicsFormulaQuestionGenerator.java | 75 ++++++++++++++++++ ...cientificAchievementQuestionGenerator.java | 76 +++++++++++++++++++ .../ScientificDiscoveryQuestionGenerator.java | 76 +++++++++++++++++++ .../ScientistBirthplaceQuestionGenerator.java | 76 +++++++++++++++++++ .../services/impl/CategoryServiceImpl.java | 3 +- 6 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java b/src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java new file mode 100644 index 00000000..8978f068 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java @@ -0,0 +1,17 @@ +package com.uniovi.components.generators.science; + +import com.uniovi.components.generators.AbstractQuestionGenerator; +import com.uniovi.entities.Category; +import com.uniovi.services.CategoryService; + +public abstract class AbstractScienceGenerator extends AbstractQuestionGenerator { + + protected AbstractScienceGenerator(CategoryService categoryService) { + super(categoryService); + } + + @Override + public Category getCategory() { + return categoryService.getCategoryByName("Science"); + } +} diff --git a/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java new file mode 100644 index 00000000..666b7052 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.science; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class MathPhysicsFormulaQuestionGenerator extends AbstractScienceGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "What is the formula for "); + put("es", "¿Cuál es la fórmula para "); + put("fr", "Quelle est la formule pour "); + } + }; + + public MathPhysicsFormulaQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?formula ?formulaLabel\n" + + "WHERE {" + + " ?formula wdt:P31 wd:Q5185279 ." + // Instance of Mathematical or physical formula + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllFormulas(JsonNode resultsNode, String correctFormula) { + List allFormulas = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String formula = result.path("formulaLabel").path("value").asText(); + if (!formula.equals(correctFormula)) { + allFormulas.add(formula); + } + } + return allFormulas; + } + + private List selectRandomIncorrectFormulas(List allFormulas, String correctFormula, int count) { + List incorrectFormulas = new ArrayList<>(); + while (incorrectFormulas.size() < count && allFormulas.size() > 0) { + int randomIndex = random.nextInt(allFormulas.size()); + String selectedFormula = allFormulas.remove(randomIndex); + if (!selectedFormula.equals(correctFormula) && !incorrectFormulas.contains(selectedFormula)) { + incorrectFormulas.add(selectedFormula); + } + } + return incorrectFormulas; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String formulaLabel = result.path("formulaLabel").path("value").asText(); + return selectRandomIncorrectFormulas(getAllFormulas(results, formulaLabel), formulaLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("formulaLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("formulaLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java new file mode 100644 index 00000000..a3812b60 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java @@ -0,0 +1,76 @@ +package com.uniovi.components.generators.science; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ScientificAchievementQuestionGenerator extends AbstractScienceGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "What significant achievement is associated with "); + put("es", "¿Qué logro significativo está asociado con "); + put("fr", "Quelle réalisation significative est associée à "); + } + }; + + public ScientificAchievementQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?scientist ?scientistLabel ?achievement ?achievementLabel\n" + + "WHERE {" + + " ?scientist wdt:P31 wd:Q5 ." + // Instance of Human + " ?scientist wdt:P166 ?achievement ." + // Notable achievement + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllAchievements(JsonNode resultsNode, String correctAchievement) { + List allAchievements = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String achievement = result.path("achievementLabel").path("value").asText(); + if (!achievement.equals(correctAchievement)) { + allAchievements.add(achievement); + } + } + return allAchievements; + } + + private List selectRandomIncorrectAchievements(List allAchievements, String correctAchievement, int count) { + List incorrectAchievements = new ArrayList<>(); + while (incorrectAchievements.size() < count && allAchievements.size() > 0) { + int randomIndex = random.nextInt(allAchievements.size()); + String selectedAchievement = allAchievements.remove(randomIndex); + if (!selectedAchievement.equals(correctAchievement) && !incorrectAchievements.contains(selectedAchievement)) { + incorrectAchievements.add(selectedAchievement); + } + } + return incorrectAchievements; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String achievementLabel = result.path("achievementLabel").path("value").asText(); + return selectRandomIncorrectAchievements(getAllAchievements(results, achievementLabel), achievementLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("achievementLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("scientistLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java new file mode 100644 index 00000000..53fc837b --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java @@ -0,0 +1,76 @@ +package com.uniovi.components.generators.science; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ScientificDiscoveryQuestionGenerator extends AbstractScienceGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Who discovered "); + put("es", "¿Quién descubrió "); + put("fr", "Qui a découvert "); + } + }; + + public ScientificDiscoveryQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?scientist ?scientistLabel ?discovery ?discoveryLabel\n" + + "WHERE {" + + " ?scientist wdt:P31 wd:Q5 ." + // Instance of Human + " ?scientist wdt:P61 ?discovery ." + // Discovery + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllDiscoveries(JsonNode resultsNode, String correctDiscovery) { + List allDiscoveries = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String discovery = result.path("discoveryLabel").path("value").asText(); + if (!discovery.equals(correctDiscovery)) { + allDiscoveries.add(discovery); + } + } + return allDiscoveries; + } + + private List selectRandomIncorrectDiscoveries(List allDiscoveries, String correctDiscovery, int count) { + List incorrectDiscoveries = new ArrayList<>(); + while (incorrectDiscoveries.size() < count && allDiscoveries.size() > 0) { + int randomIndex = random.nextInt(allDiscoveries.size()); + String selectedDiscovery = allDiscoveries.remove(randomIndex); + if (!selectedDiscovery.equals(correctDiscovery) && !incorrectDiscoveries.contains(selectedDiscovery)) { + incorrectDiscoveries.add(selectedDiscovery); + } + } + return incorrectDiscoveries; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String discoveryLabel = result.path("discoveryLabel").path("value").asText(); + return selectRandomIncorrectDiscoveries(getAllDiscoveries(results, discoveryLabel), discoveryLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("scientistLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("discoveryLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java new file mode 100644 index 00000000..2e1183a6 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java @@ -0,0 +1,76 @@ +package com.uniovi.components.generators.science; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ScientistBirthplaceQuestionGenerator extends AbstractScienceGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Where was the scientist "); + put("es", "¿Dónde nació el científico "); + put("fr", "Où est né le scientifique "); + } + }; + + public ScientistBirthplaceQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?scientist ?scientistLabel ?birthplace ?birthplaceLabel\n" + + "WHERE {" + + " ?scientist wdt:P31 wd:Q5 ." + // Instance of Human + " ?scientist wdt:P19 ?birthplace ." + // Place of birth + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllBirthplaces(JsonNode resultsNode, String correctBirthplace) { + List allBirthplaces = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String birthplace = result.path("birthplaceLabel").path("value").asText(); + if (!birthplace.equals(correctBirthplace)) { + allBirthplaces.add(birthplace); + } + } + return allBirthplaces; + } + + private List selectRandomIncorrectBirthplaces(List allBirthplaces, String correctBirthplace, int count) { + List incorrectBirthplaces = new ArrayList<>(); + while (incorrectBirthplaces.size() < count && allBirthplaces.size() > 0) { + int randomIndex = random.nextInt(allBirthplaces.size()); + String selectedBirthplace = allBirthplaces.remove(randomIndex); + if (!selectedBirthplace.equals(correctBirthplace) && !incorrectBirthplaces.contains(selectedBirthplace)) { + incorrectBirthplaces.add(selectedBirthplace); + } + } + return incorrectBirthplaces; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String birthplaceLabel = result.path("birthplaceLabel").path("value").asText(); + return selectRandomIncorrectBirthplaces(getAllBirthplaces(results, birthplaceLabel), birthplaceLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("birthplaceLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("scientistLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java index 53bd6936..a973d6cf 100644 --- a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java @@ -41,7 +41,8 @@ public Category getCategoryByName(String name) { private static final Map.Entry[] CATEGORIES = new AbstractMap.SimpleEntry[] { new AbstractMap.SimpleEntry<>("Geography", "Questions about geography"), - new AbstractMap.SimpleEntry<>("History", "Questions about history") + new AbstractMap.SimpleEntry<>("History", "Questions about history"), + new AbstractMap.SimpleEntry<>("Science", "Questions about science"), }; @PostConstruct From 8fe0cac4ac3f996705d4efe93cb81b227b18b462 Mon Sep 17 00:00:00 2001 From: RicardoDiNu Date: Sat, 6 Apr 2024 23:49:10 +0200 Subject: [PATCH 16/59] Add new question category and templates: Art --- .../generators/art/AbstractArtGenerator.java | 17 ++++ .../art/ArtMovementQuestionGenerator.java | 75 ++++++++++++++++++ .../art/ArtPeriodQuestionGenerator.java | 75 ++++++++++++++++++ .../art/ArtStyleQuestionGenerator.java | 75 ++++++++++++++++++ .../art/ArtWorkQuestionGenerator.java | 77 +++++++++++++++++++ .../services/impl/CategoryServiceImpl.java | 1 + 6 files changed, 320 insertions(+) create mode 100644 src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java b/src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java new file mode 100644 index 00000000..8d0999ef --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java @@ -0,0 +1,17 @@ +package com.uniovi.components.generators.art; + +import com.uniovi.components.generators.AbstractQuestionGenerator; +import com.uniovi.entities.Category; +import com.uniovi.services.CategoryService; + +public abstract class AbstractArtGenerator extends AbstractQuestionGenerator { + + protected AbstractArtGenerator(CategoryService categoryService) { + super(categoryService); + } + + @Override + public Category getCategory() { + return categoryService.getCategoryByName("Art"); + } +} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java new file mode 100644 index 00000000..b83b1e25 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.art; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ArtMovementQuestionGenerator extends AbstractArtGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which art movement is associated with "); + put("es", "¿Con qué movimiento artístico se asocia "); + put("fr", "Quel mouvement artistique est associé à "); + } + }; + + public ArtMovementQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?movement ?movementLabel\n" + + "WHERE {" + + " ?movement wdt:P31 wd:Q968159 ." + // Instance of Art movement + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllMovements(JsonNode resultsNode, String correctMovement) { + List allMovements = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String movement = result.path("movementLabel").path("value").asText(); + if (!movement.equals(correctMovement)) { + allMovements.add(movement); + } + } + return allMovements; + } + + private List selectRandomIncorrectMovements(List allMovements, String correctMovement, int count) { + List incorrectMovements = new ArrayList<>(); + while (incorrectMovements.size() < count && allMovements.size() > 0) { + int randomIndex = random.nextInt(allMovements.size()); + String selectedMovement = allMovements.remove(randomIndex); + if (!selectedMovement.equals(correctMovement) && !incorrectMovements.contains(selectedMovement)) { + incorrectMovements.add(selectedMovement); + } + } + return incorrectMovements; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String movementLabel = result.path("movementLabel").path("value").asText(); + return selectRandomIncorrectMovements(getAllMovements(results, movementLabel), movementLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("movementLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("movementLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java new file mode 100644 index 00000000..312c0086 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.art; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ArtPeriodQuestionGenerator extends AbstractArtGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which art period is associated with "); + put("es", "¿Con qué período artístico se asocia "); + put("fr", "Quelle période artistique est associée à "); + } + }; + + public ArtPeriodQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?period ?periodLabel\n" + + "WHERE {" + + " ?period wdt:P31 wd:Q187437 ." + // Instance of Art period + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllPeriods(JsonNode resultsNode, String correctPeriod) { + List allPeriods = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String period = result.path("periodLabel").path("value").asText(); + if (!period.equals(correctPeriod)) { + allPeriods.add(period); + } + } + return allPeriods; + } + + private List selectRandomIncorrectPeriods(List allPeriods, String correctPeriod, int count) { + List incorrectPeriods = new ArrayList<>(); + while (incorrectPeriods.size() < count && allPeriods.size() > 0) { + int randomIndex = random.nextInt(allPeriods.size()); + String selectedPeriod = allPeriods.remove(randomIndex); + if (!selectedPeriod.equals(correctPeriod) && !incorrectPeriods.contains(selectedPeriod)) { + incorrectPeriods.add(selectedPeriod); + } + } + return incorrectPeriods; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String periodLabel = result.path("periodLabel").path("value").asText(); + return selectRandomIncorrectPeriods(getAllPeriods(results, periodLabel), periodLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("periodLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("periodLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java new file mode 100644 index 00000000..19cfafeb --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.art; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ArtStyleQuestionGenerator extends AbstractArtGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which art style is associated with "); + put("es", "¿Con qué estilo artístico se asocia "); + put("fr", "Quel style artistique est associé à "); + } + }; + + public ArtStyleQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?style ?styleLabel\n" + + "WHERE {" + + " ?style wdt:P31 wd:Q179337 ." + // Instance of Art style + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllStyles(JsonNode resultsNode, String correctStyle) { + List allStyles = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String style = result.path("styleLabel").path("value").asText(); + if (!style.equals(correctStyle)) { + allStyles.add(style); + } + } + return allStyles; + } + + private List selectRandomIncorrectStyles(List allStyles, String correctStyle, int count) { + List incorrectStyles = new ArrayList<>(); + while (incorrectStyles.size() < count && allStyles.size() > 0) { + int randomIndex = random.nextInt(allStyles.size()); + String selectedStyle = allStyles.remove(randomIndex); + if (!selectedStyle.equals(correctStyle) && !incorrectStyles.contains(selectedStyle)) { + incorrectStyles.add(selectedStyle); + } + } + return incorrectStyles; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String styleLabel = result.path("styleLabel").path("value").asText(); + return selectRandomIncorrectStyles(getAllStyles(results, styleLabel), styleLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("styleLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("styleLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java new file mode 100644 index 00000000..38e40f6e --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java @@ -0,0 +1,77 @@ +package com.uniovi.components.generators.art; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ArtWorkQuestionGenerator extends AbstractArtGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Who created the artwork "); + put("es", "¿Quién creó la obra de arte "); + put("fr", "Qui a créé l'œuvre d'art "); + } + }; + + public ArtWorkQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?artist ?artistLabel ?artwork ?artworkLabel\n" + + "WHERE {" + + " ?artist wdt:P31 wd:Q5 ." + // Instance of Human + " ?artwork wdt:P31 wd:Q3305213 ." + // Instance of Artwork + " ?artwork wdt:P170 ?artist ." + // Creator + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllArtworks(JsonNode resultsNode, String correctArtwork) { + List allArtworks = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String artwork = result.path("artworkLabel").path("value").asText(); + if (!artwork.equals(correctArtwork)) { + allArtworks.add(artwork); + } + } + return allArtworks; + } + + private List selectRandomIncorrectArtworks(List allArtworks, String correctArtwork, int count) { + List incorrectArtworks = new ArrayList<>(); + while (incorrectArtworks.size() < count && allArtworks.size() > 0) { + int randomIndex = random.nextInt(allArtworks.size()); + String selectedArtwork = allArtworks.remove(randomIndex); + if (!selectedArtwork.equals(correctArtwork) && !incorrectArtworks.contains(selectedArtwork)) { + incorrectArtworks.add(selectedArtwork); + } + } + return incorrectArtworks; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String artworkLabel = result.path("artworkLabel").path("value").asText(); + return selectRandomIncorrectArtworks(getAllArtworks(results, artworkLabel), artworkLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("artistLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("artworkLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java index a973d6cf..8ddcd60e 100644 --- a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java @@ -43,6 +43,7 @@ public Category getCategoryByName(String name) { new AbstractMap.SimpleEntry<>("Geography", "Questions about geography"), new AbstractMap.SimpleEntry<>("History", "Questions about history"), new AbstractMap.SimpleEntry<>("Science", "Questions about science"), + new AbstractMap.SimpleEntry<>("Science", "Questions about art") }; @PostConstruct From 41b2333d023580a385e1c70b2a8e1e5fadfe2849 Mon Sep 17 00:00:00 2001 From: RicardoDiNu Date: Sat, 6 Apr 2024 23:50:43 +0200 Subject: [PATCH 17/59] Fix generators --- .../components/generators/art/ArtMovementQuestionGenerator.java | 1 - .../components/generators/art/ArtPeriodQuestionGenerator.java | 1 - .../components/generators/art/ArtStyleQuestionGenerator.java | 1 - .../components/generators/art/ArtWorkQuestionGenerator.java | 1 - .../generators/science/MathPhysicsFormulaQuestionGenerator.java | 1 - .../science/ScientificAchievementQuestionGenerator.java | 1 - .../generators/science/ScientificDiscoveryQuestionGenerator.java | 1 - .../generators/science/ScientistBirthplaceQuestionGenerator.java | 1 - 8 files changed, 8 deletions(-) diff --git a/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java index b83b1e25..81fef3cd 100644 --- a/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class ArtMovementQuestionGenerator extends AbstractArtGenerator { private static final Map STATEMENTS = new HashMap<>() { { diff --git a/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java index 312c0086..e005d262 100644 --- a/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class ArtPeriodQuestionGenerator extends AbstractArtGenerator { private static final Map STATEMENTS = new HashMap<>() { { diff --git a/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java index 19cfafeb..e347e643 100644 --- a/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class ArtStyleQuestionGenerator extends AbstractArtGenerator { private static final Map STATEMENTS = new HashMap<>() { { diff --git a/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java index 38e40f6e..68f95d23 100644 --- a/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class ArtWorkQuestionGenerator extends AbstractArtGenerator { private static final Map STATEMENTS = new HashMap<>() { { diff --git a/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java index 666b7052..4c907fba 100644 --- a/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class MathPhysicsFormulaQuestionGenerator extends AbstractScienceGenerator { private static final Map STATEMENTS = new HashMap<>() { { diff --git a/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java index a3812b60..36304b41 100644 --- a/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class ScientificAchievementQuestionGenerator extends AbstractScienceGenerator { private static final Map STATEMENTS = new HashMap<>() { { diff --git a/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java index 53fc837b..b868667b 100644 --- a/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class ScientificDiscoveryQuestionGenerator extends AbstractScienceGenerator { private static final Map STATEMENTS = new HashMap<>() { { diff --git a/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java index 2e1183a6..55763766 100644 --- a/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java @@ -9,7 +9,6 @@ import java.util.List; import java.util.Map; -@Component public class ScientistBirthplaceQuestionGenerator extends AbstractScienceGenerator { private static final Map STATEMENTS = new HashMap<>() { { From 61ec4bf333c49118294d01bb45b27ff704860c7a Mon Sep 17 00:00:00 2001 From: RicardoDiNu Date: Sat, 6 Apr 2024 23:54:53 +0200 Subject: [PATCH 18/59] Add new question category and templates: Movie --- .../movie/AbstractMovieGenerator.java | 17 +++++ .../movie/MovieDirectorQuestionGenerator.java | 75 +++++++++++++++++++ .../movie/MovieGenreQuestionGenerator.java | 74 ++++++++++++++++++ .../MovieReleaseYearQuestionGenerator.java | 75 +++++++++++++++++++ .../movie/OriginalTitleQuestionGenerator.java | 74 ++++++++++++++++++ .../services/impl/CategoryServiceImpl.java | 3 +- 6 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java create mode 100644 src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java b/src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java new file mode 100644 index 00000000..89eb2bef --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java @@ -0,0 +1,17 @@ +package com.uniovi.components.generators.movie; + +import com.uniovi.components.generators.AbstractQuestionGenerator; +import com.uniovi.entities.Category; +import com.uniovi.services.CategoryService; + +public abstract class AbstractMovieGenerator extends AbstractQuestionGenerator { + + protected AbstractMovieGenerator(CategoryService categoryService) { + super(categoryService); + } + + @Override + public Category getCategory() { + return categoryService.getCategoryByName("Movie"); + } +} diff --git a/src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java new file mode 100644 index 00000000..35cd2ab2 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.movie; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MovieDirectorQuestionGenerator extends AbstractMovieGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Who directed the movie "); + put("es", "¿Quién dirigió la película "); + put("fr", "Qui a dirigé le film "); + } + }; + + public MovieDirectorQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?director ?directorLabel ?movie ?movieLabel\n" + + "WHERE {" + + " ?director wdt:P31 wd:Q5 ." + // Instance of Human + " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film + " ?movie wdt:P57 ?director ." + // Director + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllMovies(JsonNode resultsNode, String correctMovie) { + List allMovies = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String movie = result.path("movieLabel").path("value").asText(); + if (!movie.equals(correctMovie)) { + allMovies.add(movie); + } + } + return allMovies; + } + + private List selectRandomIncorrectMovies(List allMovies, String correctMovie, int count) { + List incorrectMovies = new ArrayList<>(); + while (incorrectMovies.size() < count && allMovies.size() > 0) { + int randomIndex = random.nextInt(allMovies.size()); + String selectedMovie = allMovies.remove(randomIndex); + if (!selectedMovie.equals(correctMovie) && !incorrectMovies.contains(selectedMovie)) { + incorrectMovies.add(selectedMovie); + } + } + return incorrectMovies; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String movieLabel = result.path("movieLabel").path("value").asText(); + return selectRandomIncorrectMovies(getAllMovies(results, movieLabel), movieLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("directorLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("movieLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java new file mode 100644 index 00000000..8da6a045 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java @@ -0,0 +1,74 @@ +package com.uniovi.components.generators.movie; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MovieGenreQuestionGenerator extends AbstractMovieGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "Which genre does the movie "); + put("es", "¿A qué género pertenece la película "); + put("fr", "À quel genre appartient le film "); + } + }; + + public MovieGenreQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?movie ?movieLabel ?genre ?genreLabel\n" + + "WHERE {" + + " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film + " ?movie wdt:P136 ?genre ." + // Genre + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllMovies(JsonNode resultsNode, String correctMovie) { + List allMovies = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String movie = result.path("movieLabel").path("value").asText(); + if (!movie.equals(correctMovie)) { + allMovies.add(movie); + } + } + return allMovies; + } + + private List selectRandomIncorrectGenres(List allMovies, String correctMovie, int count) { + List incorrectGenres = new ArrayList<>(); + while (incorrectGenres.size() < count && allMovies.size() > 0) { + int randomIndex = random.nextInt(allMovies.size()); + String selectedMovie = allMovies.remove(randomIndex); + if (!selectedMovie.equals(correctMovie) && !incorrectGenres.contains(selectedMovie)) { + incorrectGenres.add(selectedMovie); + } + } + return incorrectGenres; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String movieLabel = result.path("movieLabel").path("value").asText(); + return selectRandomIncorrectGenres(getAllMovies(results, movieLabel), movieLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("genreLabel").path("value").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("movieLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java new file mode 100644 index 00000000..88b78d5d --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java @@ -0,0 +1,75 @@ +package com.uniovi.components.generators.movie; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MovieReleaseYearQuestionGenerator extends AbstractMovieGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "In which year was the movie "); + put("es", "¿En qué año se lanzó la película "); + put("fr", "En quelle année est sorti le film "); + } + }; + + public MovieReleaseYearQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?movie ?movieLabel ?releaseYear\n" + + "WHERE {" + + " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film + " ?movie wdt:P577 ?releaseDate ." + // Release date + " BIND(YEAR(?releaseDate) AS ?releaseYear)" + // Extract year + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllMovies(JsonNode resultsNode, String correctMovie) { + List allMovies = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String movie = result.path("movieLabel").path("value").asText(); + if (!movie.equals(correctMovie)) { + allMovies.add(movie); + } + } + return allMovies; + } + + private List selectRandomIncorrectYears(List allMovies, String correctMovie, int count) { + List incorrectYears = new ArrayList<>(); + while (incorrectYears.size() < count && allMovies.size() > 0) { + int randomIndex = random.nextInt(allMovies.size()); + String selectedMovie = allMovies.remove(randomIndex); + if (!selectedMovie.equals(correctMovie) && !incorrectYears.contains(selectedMovie)) { + incorrectYears.add(selectedMovie); + } + } + return incorrectYears; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String movieLabel = result.path("movieLabel").path("value").asText(); + return selectRandomIncorrectYears(getAllMovies(results, movieLabel), movieLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("releaseYear").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("movieLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java new file mode 100644 index 00000000..84f61091 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java @@ -0,0 +1,74 @@ +package com.uniovi.components.generators.movie; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.services.CategoryService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OriginalTitleQuestionGenerator extends AbstractMovieGenerator { + private static final Map STATEMENTS = new HashMap<>() { + { + put("en", "What is the original title of the movie "); + put("es", "¿Cuál es el título original de la película "); + put("fr", "Quel est le titre original du film "); + } + }; + + public OriginalTitleQuestionGenerator(CategoryService categoryService, String language) { + super(categoryService); + this.statement = STATEMENTS.get(language); + this.language = language; + } + + @Override + public String getQuery() { + return "SELECT DISTINCT ?movie ?movieLabel ?originalTitle\n" + + "WHERE {" + + " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film + " ?movie wdt:P1476 ?originalTitle ." + // Original title + " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + + "}"; + } + + private List getAllMovies(JsonNode resultsNode, String correctMovie) { + List allMovies = new ArrayList<>(); + for (JsonNode result : resultsNode) { + String movie = result.path("movieLabel").path("value").asText(); + if (!movie.equals(correctMovie)) { + allMovies.add(movie); + } + } + return allMovies; + } + + private List selectRandomIncorrectTitles(List allMovies, String correctMovie, int count) { + List incorrectTitles = new ArrayList<>(); + while (incorrectTitles.size() < count && allMovies.size() > 0) { + int randomIndex = random.nextInt(allMovies.size()); + String selectedMovie = allMovies.remove(randomIndex); + if (!selectedMovie.equals(correctMovie) && !incorrectTitles.contains(selectedMovie)) { + incorrectTitles.add(selectedMovie); + } + } + return incorrectTitles; + } + + @Override + protected List generateOptions(JsonNode results, JsonNode result) { + String movieLabel = result.path("movieLabel").path("value").asText(); + return selectRandomIncorrectTitles(getAllMovies(results, movieLabel), movieLabel, 3); + } + + @Override + protected String generateCorrectAnswer(JsonNode result) { + return result.path("originalTitle").asText(); + } + + @Override + protected String getQuestionSubject(JsonNode result) { + return this.statement + result.path("movieLabel").path("value").asText() + "?"; + } +} diff --git a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java index 8ddcd60e..4ba93d4d 100644 --- a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java @@ -43,7 +43,8 @@ public Category getCategoryByName(String name) { new AbstractMap.SimpleEntry<>("Geography", "Questions about geography"), new AbstractMap.SimpleEntry<>("History", "Questions about history"), new AbstractMap.SimpleEntry<>("Science", "Questions about science"), - new AbstractMap.SimpleEntry<>("Science", "Questions about art") + new AbstractMap.SimpleEntry<>("Art", "Questions about art"), + new AbstractMap.SimpleEntry<>("Movie", "Questions about movies") }; @PostConstruct From f7080ce07ca74673746f41d02bb5b6acfda06605 Mon Sep 17 00:00:00 2001 From: RicardoDiNu Date: Sun, 7 Apr 2024 00:06:57 +0200 Subject: [PATCH 19/59] Update InsertSampleDataService with the new templates --- .../services/InsertSampleDataService.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/src/main/java/com/uniovi/services/InsertSampleDataService.java b/src/main/java/com/uniovi/services/InsertSampleDataService.java index add55fcf..db1e0dff 100644 --- a/src/main/java/com/uniovi/services/InsertSampleDataService.java +++ b/src/main/java/com/uniovi/services/InsertSampleDataService.java @@ -2,8 +2,20 @@ import com.uniovi.components.MultipleQuestionGenerator; import com.uniovi.components.generators.QuestionGenerator; +import com.uniovi.components.generators.art.ArtMovementQuestionGenerator; +import com.uniovi.components.generators.art.ArtPeriodQuestionGenerator; +import com.uniovi.components.generators.art.ArtStyleQuestionGenerator; +import com.uniovi.components.generators.art.ArtWorkQuestionGenerator; import com.uniovi.components.generators.geography.*; import com.uniovi.components.generators.history.*; +import com.uniovi.components.generators.movie.MovieDirectorQuestionGenerator; +import com.uniovi.components.generators.movie.MovieGenreQuestionGenerator; +import com.uniovi.components.generators.movie.MovieReleaseYearQuestionGenerator; +import com.uniovi.components.generators.movie.OriginalTitleQuestionGenerator; +import com.uniovi.components.generators.science.MathPhysicsFormulaQuestionGenerator; +import com.uniovi.components.generators.science.ScientificAchievementQuestionGenerator; +import com.uniovi.components.generators.science.ScientificDiscoveryQuestionGenerator; +import com.uniovi.components.generators.science.ScientistBirthplaceQuestionGenerator; import com.uniovi.dto.PlayerDto; import com.uniovi.entities.Associations; import com.uniovi.entities.GameSession; @@ -110,6 +122,7 @@ public void generateSampleData() { List geographyQuestionsFrench = geographyQuestionsFr.getQuestions(); geographyQuestionsFrench.forEach(questionService::addNewQuestion); + // Generar preguntas de historia en inglés MultipleQuestionGenerator historyQuestionsEn = new MultipleQuestionGenerator( new HistoricalArtifactQuestionGeneration(categoryService, Question.ENGLISH), @@ -149,6 +162,90 @@ public void generateSampleData() { List historyQuestionsFrench = historyQuestionsFr.getQuestions(); historyQuestionsFrench.forEach(questionService::addNewQuestion); + + MultipleQuestionGenerator scienceQuestionsEn = new MultipleQuestionGenerator( + new MathPhysicsFormulaQuestionGenerator(categoryService, Question.ENGLISH), + new ScientificAchievementQuestionGenerator(categoryService, Question.ENGLISH), + new ScientificDiscoveryQuestionGenerator(categoryService, Question.ENGLISH), + new ScientistBirthplaceQuestionGenerator(categoryService, Question.ENGLISH) + ); + List scienceQuestions = scienceQuestionsEn.getQuestions(); + scienceQuestions.forEach(questionService::addNewQuestion); + + MultipleQuestionGenerator scienceQuestionsEs = new MultipleQuestionGenerator( + new MathPhysicsFormulaQuestionGenerator(categoryService, Question.SPANISH), + new ScientificAchievementQuestionGenerator(categoryService, Question.SPANISH), + new ScientificDiscoveryQuestionGenerator(categoryService, Question.SPANISH), + new ScientistBirthplaceQuestionGenerator(categoryService, Question.SPANISH) + ); + List scienceQuestionsSpanish = scienceQuestionsEs.getQuestions(); + scienceQuestionsSpanish.forEach(questionService::addNewQuestion); + + MultipleQuestionGenerator scienceQuestionsFr = new MultipleQuestionGenerator( + new MathPhysicsFormulaQuestionGenerator(categoryService, Question.FRENCH), + new ScientificAchievementQuestionGenerator(categoryService, Question.FRENCH), + new ScientificDiscoveryQuestionGenerator(categoryService, Question.FRENCH), + new ScientistBirthplaceQuestionGenerator(categoryService, Question.FRENCH) + ); + List scienceQuestionsFrench = scienceQuestionsFr.getQuestions(); + scienceQuestionsFrench.forEach(questionService::addNewQuestion); + + + MultipleQuestionGenerator artQuestionsEn = new MultipleQuestionGenerator( + new ArtMovementQuestionGenerator(categoryService, Question.ENGLISH), + new ArtPeriodQuestionGenerator(categoryService, Question.ENGLISH), + new ArtStyleQuestionGenerator(categoryService, Question.ENGLISH), + new ArtWorkQuestionGenerator(categoryService, Question.ENGLISH) + ); + List artQuestions = artQuestionsEn.getQuestions(); + artQuestions.forEach(questionService::addNewQuestion); + + MultipleQuestionGenerator artQuestionsEs = new MultipleQuestionGenerator( + new ArtMovementQuestionGenerator(categoryService, Question.SPANISH), + new ArtPeriodQuestionGenerator(categoryService, Question.SPANISH), + new ArtStyleQuestionGenerator(categoryService, Question.SPANISH), + new ArtWorkQuestionGenerator(categoryService, Question.SPANISH) + ); + List artQuestionsSpanish = artQuestionsEs.getQuestions(); + artQuestionsSpanish.forEach(questionService::addNewQuestion); + + MultipleQuestionGenerator artQuestionsFr = new MultipleQuestionGenerator( + new ArtMovementQuestionGenerator(categoryService, Question.FRENCH), + new ArtPeriodQuestionGenerator(categoryService, Question.FRENCH), + new ArtStyleQuestionGenerator(categoryService, Question.FRENCH), + new ArtWorkQuestionGenerator(categoryService, Question.FRENCH) + ); + List artQuestionsFrench = artQuestionsFr.getQuestions(); + artQuestionsFrench.forEach(questionService::addNewQuestion); + + + MultipleQuestionGenerator movieQuestionsEn = new MultipleQuestionGenerator( + new MovieDirectorQuestionGenerator(categoryService, Question.ENGLISH), + new MovieGenreQuestionGenerator(categoryService, Question.ENGLISH), + new MovieReleaseYearQuestionGenerator(categoryService, Question.ENGLISH), + new OriginalTitleQuestionGenerator(categoryService, Question.ENGLISH) + ); + List movieQuestions = movieQuestionsEn.getQuestions(); + movieQuestions.forEach(questionService::addNewQuestion); + + MultipleQuestionGenerator movieQuestionsEs = new MultipleQuestionGenerator( + new MovieDirectorQuestionGenerator(categoryService, Question.SPANISH), + new MovieGenreQuestionGenerator(categoryService, Question.SPANISH), + new MovieReleaseYearQuestionGenerator(categoryService, Question.SPANISH), + new OriginalTitleQuestionGenerator(categoryService, Question.SPANISH) + ); + List movieQuestionsSpanish = movieQuestionsEs.getQuestions(); + movieQuestionsSpanish.forEach(questionService::addNewQuestion); + + MultipleQuestionGenerator movieQuestionsFr = new MultipleQuestionGenerator( + new MovieDirectorQuestionGenerator(categoryService, Question.FRENCH), + new MovieGenreQuestionGenerator(categoryService, Question.FRENCH), + new MovieReleaseYearQuestionGenerator(categoryService, Question.FRENCH), + new OriginalTitleQuestionGenerator(categoryService, Question.FRENCH) + ); + List movieQuestionsFrench = movieQuestionsFr.getQuestions(); + movieQuestionsFrench.forEach(questionService::addNewQuestion); + log.info("Sample questions inserted"); } From 5aaa8dbac24a22a903dd1b969b495f2cab8d25a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20D=C3=ADaz=20N=C3=BA=C3=B1ez?= Date: Mon, 15 Apr 2024 16:48:59 +0200 Subject: [PATCH 20/59] Undo CategoryServiceImpl and InsertSampleDataService changes to only add the new generators classes and don't affect the current code --- .../services/InsertSampleDataService.java | 196 +++--------------- .../services/impl/CategoryServiceImpl.java | 8 +- 2 files changed, 28 insertions(+), 176 deletions(-) diff --git a/src/main/java/com/uniovi/services/InsertSampleDataService.java b/src/main/java/com/uniovi/services/InsertSampleDataService.java index db1e0dff..ff76371a 100644 --- a/src/main/java/com/uniovi/services/InsertSampleDataService.java +++ b/src/main/java/com/uniovi/services/InsertSampleDataService.java @@ -2,20 +2,9 @@ import com.uniovi.components.MultipleQuestionGenerator; import com.uniovi.components.generators.QuestionGenerator; -import com.uniovi.components.generators.art.ArtMovementQuestionGenerator; -import com.uniovi.components.generators.art.ArtPeriodQuestionGenerator; -import com.uniovi.components.generators.art.ArtStyleQuestionGenerator; -import com.uniovi.components.generators.art.ArtWorkQuestionGenerator; -import com.uniovi.components.generators.geography.*; -import com.uniovi.components.generators.history.*; -import com.uniovi.components.generators.movie.MovieDirectorQuestionGenerator; -import com.uniovi.components.generators.movie.MovieGenreQuestionGenerator; -import com.uniovi.components.generators.movie.MovieReleaseYearQuestionGenerator; -import com.uniovi.components.generators.movie.OriginalTitleQuestionGenerator; -import com.uniovi.components.generators.science.MathPhysicsFormulaQuestionGenerator; -import com.uniovi.components.generators.science.ScientificAchievementQuestionGenerator; -import com.uniovi.components.generators.science.ScientificDiscoveryQuestionGenerator; -import com.uniovi.components.generators.science.ScientistBirthplaceQuestionGenerator; +import com.uniovi.components.generators.geography.BorderQuestionGenerator; +import com.uniovi.components.generators.geography.CapitalQuestionGenerator; +import com.uniovi.components.generators.geography.ContinentQuestionGeneration; import com.uniovi.dto.PlayerDto; import com.uniovi.entities.Associations; import com.uniovi.entities.GameSession; @@ -25,7 +14,6 @@ import com.uniovi.repositories.QuestionRepository; import jakarta.annotation.PostConstruct; import jakarta.transaction.Transactional; -import org.hibernate.validator.constraints.Currency; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -34,6 +22,7 @@ import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; +import java.io.IOException; import java.time.LocalDateTime; import java.util.*; @@ -61,7 +50,7 @@ public InsertSampleDataService(PlayerService playerService, QuestionService ques @Transactional @EventListener(ApplicationReadyEvent.class) // Uncomment this line to insert sample data on startup - public void insertSampleQuestions() { + public void insertSampleQuestions() throws InterruptedException, IOException { if (!playerService.getUserByEmail("test@test.com").isPresent()) { PlayerDto player = new PlayerDto(); player.setEmail("test@test.com"); @@ -80,173 +69,40 @@ public void insertSampleQuestions() { } @Transactional - public void generateSampleData() { + public void generateTestQuestions() { + questionRepository.deleteAll(); + questionService.testQuestions(4); + } + + @Transactional + public void generateSampleData() throws InterruptedException, IOException { + questionRepository.deleteAll(); - // Generar preguntas de geografía en inglés - MultipleQuestionGenerator geographyQuestionsEn = new MultipleQuestionGenerator( + MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( new ContinentQuestionGeneration(categoryService, Question.ENGLISH), new CapitalQuestionGenerator(categoryService, Question.ENGLISH), - new BorderQuestionGenerator(categoryService, Question.ENGLISH), - new AreaQuestionGenerator(categoryService, Question.ENGLISH), - new CurrencyQuestionGenerator(categoryService, Question.ENGLISH), - new LanguageQuestionGenerator(categoryService, Question.ENGLISH), - new PopulationQuestionGenerator(categoryService, Question.ENGLISH) + new BorderQuestionGenerator(categoryService, Question.ENGLISH) ); - List geographyQuestions = geographyQuestionsEn.getQuestions(); - geographyQuestions.forEach(questionService::addNewQuestion); + List questionsEn = allQuestionGenerator.getQuestions(); + questionsEn.forEach(questionService::addNewQuestion); - // Generar preguntas de geografía en español - MultipleQuestionGenerator geographyQuestionsEs = new MultipleQuestionGenerator( + allQuestionGenerator = new MultipleQuestionGenerator( new ContinentQuestionGeneration(categoryService, Question.SPANISH), new CapitalQuestionGenerator(categoryService, Question.SPANISH), - new BorderQuestionGenerator(categoryService, Question.SPANISH), - new AreaQuestionGenerator(categoryService, Question.SPANISH), - new CurrencyQuestionGenerator(categoryService, Question.SPANISH), - new LanguageQuestionGenerator(categoryService, Question.SPANISH), - new PopulationQuestionGenerator(categoryService, Question.SPANISH) + new BorderQuestionGenerator(categoryService, Question.SPANISH) ); - List geographyQuestionsSpanish = geographyQuestionsEs.getQuestions(); - geographyQuestionsSpanish.forEach(questionService::addNewQuestion); + List questionsEs = allQuestionGenerator.getQuestions(); + questionsEs.forEach(questionService::addNewQuestion); - // Generar preguntas de geografía en francés - MultipleQuestionGenerator geographyQuestionsFr = new MultipleQuestionGenerator( + allQuestionGenerator = new MultipleQuestionGenerator( new ContinentQuestionGeneration(categoryService, Question.FRENCH), new CapitalQuestionGenerator(categoryService, Question.FRENCH), - new BorderQuestionGenerator(categoryService, Question.FRENCH), - new AreaQuestionGenerator(categoryService, Question.FRENCH), - new CurrencyQuestionGenerator(categoryService, Question.FRENCH), - new LanguageQuestionGenerator(categoryService, Question.FRENCH), - new PopulationQuestionGenerator(categoryService, Question.FRENCH) - ); - List geographyQuestionsFrench = geographyQuestionsFr.getQuestions(); - geographyQuestionsFrench.forEach(questionService::addNewQuestion); - - - // Generar preguntas de historia en inglés - MultipleQuestionGenerator historyQuestionsEn = new MultipleQuestionGenerator( - new HistoricalArtifactQuestionGeneration(categoryService, Question.ENGLISH), - new HistoricalBattleQuestionGeneration(categoryService, Question.ENGLISH), - new HistoricalDynastyQuestionGeneration(categoryService, Question.ENGLISH), - new HistoricalEventQuestionGeneration(categoryService, Question.ENGLISH), - new HistoricalInventionQuestionGeneration(categoryService, Question.ENGLISH), - new HistoricalPeriodQuestionGeneration(categoryService, Question.ENGLISH), - new HistoricalLeaderQuestionGeneration(categoryService, Question.ENGLISH) - ); - List historyQuestions = historyQuestionsEn.getQuestions(); - historyQuestions.forEach(questionService::addNewQuestion); - - // Generar preguntas de historia en español - MultipleQuestionGenerator historyQuestionsEs = new MultipleQuestionGenerator( - new HistoricalArtifactQuestionGeneration(categoryService, Question.SPANISH), - new HistoricalBattleQuestionGeneration(categoryService, Question.SPANISH), - new HistoricalDynastyQuestionGeneration(categoryService, Question.SPANISH), - new HistoricalEventQuestionGeneration(categoryService, Question.SPANISH), - new HistoricalInventionQuestionGeneration(categoryService, Question.SPANISH), - new HistoricalPeriodQuestionGeneration(categoryService, Question.SPANISH), - new HistoricalLeaderQuestionGeneration(categoryService, Question.SPANISH) - ); - List historyQuestionsSpanish = historyQuestionsEs.getQuestions(); - historyQuestionsSpanish.forEach(questionService::addNewQuestion); - - // Generar preguntas de historia en francés - MultipleQuestionGenerator historyQuestionsFr = new MultipleQuestionGenerator( - new HistoricalArtifactQuestionGeneration(categoryService, Question.FRENCH), - new HistoricalBattleQuestionGeneration(categoryService, Question.FRENCH), - new HistoricalDynastyQuestionGeneration(categoryService, Question.FRENCH), - new HistoricalEventQuestionGeneration(categoryService, Question.FRENCH), - new HistoricalInventionQuestionGeneration(categoryService, Question.FRENCH), - new HistoricalPeriodQuestionGeneration(categoryService, Question.FRENCH), - new HistoricalLeaderQuestionGeneration(categoryService, Question.FRENCH) - ); - List historyQuestionsFrench = historyQuestionsFr.getQuestions(); - historyQuestionsFrench.forEach(questionService::addNewQuestion); - - - MultipleQuestionGenerator scienceQuestionsEn = new MultipleQuestionGenerator( - new MathPhysicsFormulaQuestionGenerator(categoryService, Question.ENGLISH), - new ScientificAchievementQuestionGenerator(categoryService, Question.ENGLISH), - new ScientificDiscoveryQuestionGenerator(categoryService, Question.ENGLISH), - new ScientistBirthplaceQuestionGenerator(categoryService, Question.ENGLISH) - ); - List scienceQuestions = scienceQuestionsEn.getQuestions(); - scienceQuestions.forEach(questionService::addNewQuestion); - - MultipleQuestionGenerator scienceQuestionsEs = new MultipleQuestionGenerator( - new MathPhysicsFormulaQuestionGenerator(categoryService, Question.SPANISH), - new ScientificAchievementQuestionGenerator(categoryService, Question.SPANISH), - new ScientificDiscoveryQuestionGenerator(categoryService, Question.SPANISH), - new ScientistBirthplaceQuestionGenerator(categoryService, Question.SPANISH) + new BorderQuestionGenerator(categoryService, Question.FRENCH) ); - List scienceQuestionsSpanish = scienceQuestionsEs.getQuestions(); - scienceQuestionsSpanish.forEach(questionService::addNewQuestion); - - MultipleQuestionGenerator scienceQuestionsFr = new MultipleQuestionGenerator( - new MathPhysicsFormulaQuestionGenerator(categoryService, Question.FRENCH), - new ScientificAchievementQuestionGenerator(categoryService, Question.FRENCH), - new ScientificDiscoveryQuestionGenerator(categoryService, Question.FRENCH), - new ScientistBirthplaceQuestionGenerator(categoryService, Question.FRENCH) - ); - List scienceQuestionsFrench = scienceQuestionsFr.getQuestions(); - scienceQuestionsFrench.forEach(questionService::addNewQuestion); - - - MultipleQuestionGenerator artQuestionsEn = new MultipleQuestionGenerator( - new ArtMovementQuestionGenerator(categoryService, Question.ENGLISH), - new ArtPeriodQuestionGenerator(categoryService, Question.ENGLISH), - new ArtStyleQuestionGenerator(categoryService, Question.ENGLISH), - new ArtWorkQuestionGenerator(categoryService, Question.ENGLISH) - ); - List artQuestions = artQuestionsEn.getQuestions(); - artQuestions.forEach(questionService::addNewQuestion); - - MultipleQuestionGenerator artQuestionsEs = new MultipleQuestionGenerator( - new ArtMovementQuestionGenerator(categoryService, Question.SPANISH), - new ArtPeriodQuestionGenerator(categoryService, Question.SPANISH), - new ArtStyleQuestionGenerator(categoryService, Question.SPANISH), - new ArtWorkQuestionGenerator(categoryService, Question.SPANISH) - ); - List artQuestionsSpanish = artQuestionsEs.getQuestions(); - artQuestionsSpanish.forEach(questionService::addNewQuestion); - - MultipleQuestionGenerator artQuestionsFr = new MultipleQuestionGenerator( - new ArtMovementQuestionGenerator(categoryService, Question.FRENCH), - new ArtPeriodQuestionGenerator(categoryService, Question.FRENCH), - new ArtStyleQuestionGenerator(categoryService, Question.FRENCH), - new ArtWorkQuestionGenerator(categoryService, Question.FRENCH) - ); - List artQuestionsFrench = artQuestionsFr.getQuestions(); - artQuestionsFrench.forEach(questionService::addNewQuestion); - - - MultipleQuestionGenerator movieQuestionsEn = new MultipleQuestionGenerator( - new MovieDirectorQuestionGenerator(categoryService, Question.ENGLISH), - new MovieGenreQuestionGenerator(categoryService, Question.ENGLISH), - new MovieReleaseYearQuestionGenerator(categoryService, Question.ENGLISH), - new OriginalTitleQuestionGenerator(categoryService, Question.ENGLISH) - ); - List movieQuestions = movieQuestionsEn.getQuestions(); - movieQuestions.forEach(questionService::addNewQuestion); - - MultipleQuestionGenerator movieQuestionsEs = new MultipleQuestionGenerator( - new MovieDirectorQuestionGenerator(categoryService, Question.SPANISH), - new MovieGenreQuestionGenerator(categoryService, Question.SPANISH), - new MovieReleaseYearQuestionGenerator(categoryService, Question.SPANISH), - new OriginalTitleQuestionGenerator(categoryService, Question.SPANISH) - ); - List movieQuestionsSpanish = movieQuestionsEs.getQuestions(); - movieQuestionsSpanish.forEach(questionService::addNewQuestion); - - MultipleQuestionGenerator movieQuestionsFr = new MultipleQuestionGenerator( - new MovieDirectorQuestionGenerator(categoryService, Question.FRENCH), - new MovieGenreQuestionGenerator(categoryService, Question.FRENCH), - new MovieReleaseYearQuestionGenerator(categoryService, Question.FRENCH), - new OriginalTitleQuestionGenerator(categoryService, Question.FRENCH) - ); - List movieQuestionsFrench = movieQuestionsFr.getQuestions(); - movieQuestionsFrench.forEach(questionService::addNewQuestion); + List questionsFr = allQuestionGenerator.getQuestions(); + questionsFr.forEach(questionService::addNewQuestion); log.info("Sample questions inserted"); } - -} +} \ No newline at end of file diff --git a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java index 4ba93d4d..cf3c3545 100644 --- a/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/CategoryServiceImpl.java @@ -40,11 +40,7 @@ public Category getCategoryByName(String name) { } private static final Map.Entry[] CATEGORIES = new AbstractMap.SimpleEntry[] { - new AbstractMap.SimpleEntry<>("Geography", "Questions about geography"), - new AbstractMap.SimpleEntry<>("History", "Questions about history"), - new AbstractMap.SimpleEntry<>("Science", "Questions about science"), - new AbstractMap.SimpleEntry<>("Art", "Questions about art"), - new AbstractMap.SimpleEntry<>("Movie", "Questions about movies") + new AbstractMap.SimpleEntry<>("Geography", "Questions about geography") }; @PostConstruct @@ -56,4 +52,4 @@ public void init() { } } } -} +} \ No newline at end of file From e603718cfe3ab0c91703e7d7757ac248754a828f Mon Sep 17 00:00:00 2001 From: Pelayori <31128562+Pelayori@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:30:17 +0200 Subject: [PATCH 21/59] Remove old commented code --- .../java/com/uniovi/controllers/GameController.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/main/java/com/uniovi/controllers/GameController.java b/src/main/java/com/uniovi/controllers/GameController.java index ad8a7506..f8c0ffa3 100644 --- a/src/main/java/com/uniovi/controllers/GameController.java +++ b/src/main/java/com/uniovi/controllers/GameController.java @@ -79,32 +79,23 @@ public String getCheckResult(@PathVariable Long idQuestion, @PathVariable Long i if(idAnswer == -1 || getRemainingTime(gameSession) <= 0) { - //model.addAttribute("correctAnswer", gameSession.getCurrentQuestion().getCorrectAnswer()); - //model.addAttribute("messageKey", "timeRunOut.result"); - //model.addAttribute("logoImage", "/images/logo_incorrect.svg"); gameSession.addAnsweredQuestion(gameSession.getCurrentQuestion()); gameSession.addQuestion(false, 0); } else if(questionService.checkAnswer(idQuestion, idAnswer)) { - //model.addAttribute("messageKey", "correctAnswer.result"); - //model.addAttribute("logoImage", "/images/logo_correct.svg"); - if (!gameSession.isAnswered(gameSession.getCurrentQuestion())) { gameSession.addQuestion(true, getRemainingTime(gameSession)); gameSession.addAnsweredQuestion(gameSession.getCurrentQuestion()); } } else { - //model.addAttribute("correctAnswer", gameSession.getCurrentQuestion().getCorrectAnswer()); - //model.addAttribute("messageKey", "failedAnswer.result"); - //model.addAttribute("logoImage", "/images/logo_incorrect.svg"); gameSession.addAnsweredQuestion(gameSession.getCurrentQuestion()); gameSession.addQuestion(false, 0); } session.setAttribute("hasJustAnswered", true); gameSession.getNextQuestion(); - //return "game/fragments/questionResult"; + return updateGame(model, session); } From 16887719f4936f6f85dc7e2c3fa2d5b6a9f1d45f Mon Sep 17 00:00:00 2001 From: uo287545 Date: Wed, 24 Apr 2024 20:34:01 +0200 Subject: [PATCH 22/59] First version of the base JSON done --- .../static/JSON/QuestionTemplates.json | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/resources/static/JSON/QuestionTemplates.json diff --git a/src/main/resources/static/JSON/QuestionTemplates.json b/src/main/resources/static/JSON/QuestionTemplates.json new file mode 100644 index 00000000..e7c58eed --- /dev/null +++ b/src/main/resources/static/JSON/QuestionTemplates.json @@ -0,0 +1,22 @@ +{ + "language_placeholder": "[LANGUAGE]", + "categories": [ + { + "name": "Geography", + "questions": [ + { + "type": "capital", + "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre fronteras" + }, + { + "type": "border", + "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre fronteras" + }, + { + "type": "continent", + "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre continentes" + } + ] + } + ] +} From 48fe6057a6c3e7dced82a55c7eac4ff8bf50e41c Mon Sep 17 00:00:00 2001 From: uo287545 Date: Wed, 24 Apr 2024 20:37:53 +0200 Subject: [PATCH 23/59] Added statements for the capital question --- .../resources/static/JSON/QuestionTemplates.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/resources/static/JSON/QuestionTemplates.json b/src/main/resources/static/JSON/QuestionTemplates.json index e7c58eed..0fff93f2 100644 --- a/src/main/resources/static/JSON/QuestionTemplates.json +++ b/src/main/resources/static/JSON/QuestionTemplates.json @@ -6,7 +6,21 @@ "questions": [ { "type": "capital", - "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre fronteras" + "statements": [ + { + "language": "es", + "statement": "¿Cuál es la capital de [COUNTRY]?" + }, + { + "language": "en", + "statement": "What is the capital of [COUNTRY]?" + }, + { + "language": "fr", + "statement": "Quelle est la capitale de [COUNTRY]?" + } + ], + "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre capitales" }, { "type": "border", From 0c7930b671d9f84b8ae52b77ee05d847faaa68a7 Mon Sep 17 00:00:00 2001 From: Pelayori <31128562+Pelayori@users.noreply.github.com> Date: Thu, 25 Apr 2024 01:00:53 +0200 Subject: [PATCH 24/59] Add table and dropdown to user management --- .../uniovi/configuration/SecurityConfig.java | 1 + .../uniovi/controllers/PlayersController.java | 22 ++++++++ src/main/java/com/uniovi/entities/Role.java | 5 ++ .../uniovi/repositories/PlayerRepository.java | 4 ++ .../services/InsertSampleDataService.java | 41 +++++++------- .../com/uniovi/services/PlayerService.java | 9 ++++ .../services/impl/PlayerServiceImpl.java | 7 +++ src/main/resources/messages.properties | 14 ++++- src/main/resources/messages_en.properties | 1 + src/main/resources/messages_es.properties | 1 + src/main/resources/messages_fr.properties | 1 + src/main/resources/static/css/admin.css | 22 ++++++++ src/main/resources/static/css/custom.css | 10 ++++ .../resources/templates/fragments/head.html | 2 +- .../templates/fragments/pagination.html | 4 +- .../fragments/paginationDynamic.html | 36 +++++++++++++ .../templates/player/admin/admin.html | 54 +++++++++++++++++++ .../player/admin/questionManagement.html | 1 + .../player/admin/userManagement.html | 30 +++++++++++ src/main/resources/templates/player/home.html | 13 ++--- 20 files changed, 248 insertions(+), 30 deletions(-) create mode 100644 src/main/resources/static/css/admin.css create mode 100644 src/main/resources/templates/fragments/paginationDynamic.html create mode 100644 src/main/resources/templates/player/admin/admin.html create mode 100644 src/main/resources/templates/player/admin/questionManagement.html create mode 100644 src/main/resources/templates/player/admin/userManagement.html diff --git a/src/main/java/com/uniovi/configuration/SecurityConfig.java b/src/main/java/com/uniovi/configuration/SecurityConfig.java index c0af5d20..674cd83f 100644 --- a/src/main/java/com/uniovi/configuration/SecurityConfig.java +++ b/src/main/java/com/uniovi/configuration/SecurityConfig.java @@ -48,6 +48,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/api/**").permitAll() .requestMatchers("/game/**").authenticated() .requestMatchers("/ranking/playerRanking").authenticated() + .requestMatchers("/admin/**").hasAuthority("ROLE_ADMIN") .requestMatchers("/**").permitAll() ).formLogin( form -> form diff --git a/src/main/java/com/uniovi/controllers/PlayersController.java b/src/main/java/com/uniovi/controllers/PlayersController.java index d291b6c6..afbc33c1 100644 --- a/src/main/java/com/uniovi/controllers/PlayersController.java +++ b/src/main/java/com/uniovi/controllers/PlayersController.java @@ -122,4 +122,26 @@ public String showPlayerRanking(Pageable pageable, Model model, Principal princi return "ranking/playerRanking"; } + + // ----- Admin endpoints ----- + + @GetMapping("/player/admin") + public String showAdminPanel(Model model) { + return "player/admin/admin"; + } + + @GetMapping("/player/admin/userManagement") + public String showUserManagementFragment(Model model, Pageable pageable) { + model.addAttribute("endpoint", "/player/admin/userManagement"); + Page users = playerService.getPlayersPage(pageable); + model.addAttribute("page", users); + model.addAttribute("users", users.getContent()); + + return "player/admin/userManagement"; + } + + @GetMapping("/player/admin/questionManagement") + public String showQuestionManagementFragment() { + return "player/admin/questionManagement"; + } } diff --git a/src/main/java/com/uniovi/entities/Role.java b/src/main/java/com/uniovi/entities/Role.java index c767c425..0d4d45c0 100644 --- a/src/main/java/com/uniovi/entities/Role.java +++ b/src/main/java/com/uniovi/entities/Role.java @@ -22,4 +22,9 @@ public class Role { public Role(String name) { this.name = name; } + + @Override + public String toString() { + return name; + } } diff --git a/src/main/java/com/uniovi/repositories/PlayerRepository.java b/src/main/java/com/uniovi/repositories/PlayerRepository.java index 77c2d9f8..cf4f0a98 100644 --- a/src/main/java/com/uniovi/repositories/PlayerRepository.java +++ b/src/main/java/com/uniovi/repositories/PlayerRepository.java @@ -1,9 +1,13 @@ package com.uniovi.repositories; import com.uniovi.entities.Player; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.repository.CrudRepository; public interface PlayerRepository extends CrudRepository { Player findByEmail(String email); Player findByUsername(String nickname); + + Page findAll(Pageable pageable); } diff --git a/src/main/java/com/uniovi/services/InsertSampleDataService.java b/src/main/java/com/uniovi/services/InsertSampleDataService.java index f51a0ed8..d5415fc7 100644 --- a/src/main/java/com/uniovi/services/InsertSampleDataService.java +++ b/src/main/java/com/uniovi/services/InsertSampleDataService.java @@ -32,35 +32,36 @@ public class InsertSampleDataService { private final QuestionService questionService; private final CategoryService categoryService; private final QuestionRepository questionRepository; - private final GameSessionRepository gameSessionRepository; - private Environment environment; + private final Environment environment; - private Logger log = LoggerFactory.getLogger(InsertSampleDataService.class); + private final Logger log = LoggerFactory.getLogger(InsertSampleDataService.class); public InsertSampleDataService(PlayerService playerService, QuestionService questionService, CategoryService categoryService, QuestionRepository questionRepository, - GameSessionRepository gameSessionRepository, Environment environment) { + Environment environment) { this.playerService = playerService; this.questionService = questionService; this.categoryService = categoryService; this.questionRepository = questionRepository; - this.gameSessionRepository = gameSessionRepository; this.environment = environment; } @Transactional @EventListener(ApplicationReadyEvent.class) // Uncomment this line to insert sample data on startup public void insertSampleQuestions() throws InterruptedException, IOException { - if (!playerService.getUserByEmail("test@test.com").isPresent()) { + if (playerService.getUserByEmail("test@test.com").isEmpty()) { PlayerDto player = new PlayerDto(); player.setEmail("test@test.com"); player.setUsername("test"); player.setPassword("test"); - player.setRoles(new String[]{"ROLE_USER"}); + if (isProfileActive("prod")) + player.setRoles(new String[]{"ROLE_USER"}); + else + player.setRoles(new String[]{"ROLE_USER", "ROLE_ADMIN"}); playerService.generateApiKey(playerService.addNewPlayer(player)); } - if (Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("test")))) { + if (isProfileActive("test")) { log.info("Test profile active, skipping sample data insertion"); return; } @@ -80,29 +81,33 @@ public void generateSampleData() throws InterruptedException, IOException { questionRepository.deleteAll(); MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( - new ContinentQuestionGeneration(categoryService, Question.ENGLISH), - new CapitalQuestionGenerator(categoryService, Question.ENGLISH), - new BorderQuestionGenerator(categoryService, Question.ENGLISH) + //new ContinentQuestionGeneration(categoryService, Question.ENGLISH), + //new CapitalQuestionGenerator(categoryService, Question.ENGLISH), + //new BorderQuestionGenerator(categoryService, Question.ENGLISH) ); List questionsEn = allQuestionGenerator.getQuestions(); questionsEn.forEach(questionService::addNewQuestion); allQuestionGenerator = new MultipleQuestionGenerator( - new ContinentQuestionGeneration(categoryService, Question.SPANISH), - new CapitalQuestionGenerator(categoryService, Question.SPANISH), + //new ContinentQuestionGeneration(categoryService, Question.SPANISH), + //new CapitalQuestionGenerator(categoryService, Question.SPANISH), new BorderQuestionGenerator(categoryService, Question.SPANISH) ); List questionsEs = allQuestionGenerator.getQuestions(); questionsEs.forEach(questionService::addNewQuestion); - allQuestionGenerator = new MultipleQuestionGenerator( - new ContinentQuestionGeneration(categoryService, Question.FRENCH), - new CapitalQuestionGenerator(categoryService, Question.FRENCH), - new BorderQuestionGenerator(categoryService, Question.FRENCH) - ); + //allQuestionGenerator = new MultipleQuestionGenerator( + // new ContinentQuestionGeneration(categoryService, Question.FRENCH), + // new CapitalQuestionGenerator(categoryService, Question.FRENCH), + // new BorderQuestionGenerator(categoryService, Question.FRENCH) + //); List questionsFr = allQuestionGenerator.getQuestions(); questionsFr.forEach(questionService::addNewQuestion); log.info("Sample questions inserted"); } + + public boolean isProfileActive(String profile) { + return Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase(profile))); + } } diff --git a/src/main/java/com/uniovi/services/PlayerService.java b/src/main/java/com/uniovi/services/PlayerService.java index f59669e3..0cf320a2 100644 --- a/src/main/java/com/uniovi/services/PlayerService.java +++ b/src/main/java/com/uniovi/services/PlayerService.java @@ -4,6 +4,8 @@ import com.uniovi.entities.Player; import com.uniovi.repositories.PlayerRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; @@ -72,4 +74,11 @@ public interface PlayerService { * @param id The id of the player to delete */ void deletePlayer(Long id); + + /** + * Get a page with all the players in the database + * @param pageable The page information + * @return A page with all the players + */ + Page getPlayersPage(Pageable pageable); } diff --git a/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java b/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java index f4fa462d..d3b868a4 100644 --- a/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java @@ -10,6 +10,8 @@ import com.uniovi.services.PlayerService; import com.uniovi.services.RoleService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import com.uniovi.entities.Role; @@ -136,4 +138,9 @@ public void updatePlayer(Long id, PlayerDto playerDto) { public void deletePlayer(Long id) { playerRepository.deleteById(id); } + + @Override + public Page getPlayersPage(Pageable pageable) { + return playerRepository.findAll(pageable); + } } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 2b91abb1..7130729c 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -13,6 +13,7 @@ navbar.toEnglish=Inglés navbar.toSpanish=Español navbar.toFrench=Francés navbar.currentLanguage=Español +navbar.section.admin=Panel de administración # Buttons for non-authenticated users navbar.signup=Regístrate @@ -114,4 +115,15 @@ game.continue=Siguiente pregunta answer.correct=La respuesta correcta era: game.points=Puntos: game.currentQuestion=Pregunta: -game.finish=El juego ha terminado. Tu puntuación ha sido: \ No newline at end of file +game.finish=El juego ha terminado. Tu puntuación ha sido: + + +# -------------------Statements for the admin section--------------------- +admin.section.user.management=Administración de usuarios +admin.section.question.management=Administración de preguntas +role.label=Roles +user.details=Acciones + +# -------------------Statements for the page management--------------------- +page.first=Primera +page.last=Última \ No newline at end of file diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 97f0f133..901ef79b 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -13,6 +13,7 @@ navbar.toEnglish=English navbar.toSpanish=Spanish navbar.toFrench=French navbar.currentLanguage=English +navbar.section.admin=Administration Section # Buttons for non-authenticated users navbar.signup=Sign Up diff --git a/src/main/resources/messages_es.properties b/src/main/resources/messages_es.properties index 174dad48..61bf6b83 100644 --- a/src/main/resources/messages_es.properties +++ b/src/main/resources/messages_es.properties @@ -13,6 +13,7 @@ navbar.toEnglish=Inglés navbar.toSpanish=Español navbar.toFrench=Francés navbar.currentLanguage=Español +navbar.section.admin=Panel de administración # Buttons for non-authenticated users navbar.signup=Regístrate diff --git a/src/main/resources/messages_fr.properties b/src/main/resources/messages_fr.properties index 1f5d2b22..616c23b8 100644 --- a/src/main/resources/messages_fr.properties +++ b/src/main/resources/messages_fr.properties @@ -12,6 +12,7 @@ navbar.toEnglish=Anglais navbar.toSpanish=Espagnol navbar.toFrench=Français navbar.currentLanguage=Français +navbar.section.admin=Espace administrateur navbar.signup=S'inscrire navbar.login=Se connecter diff --git a/src/main/resources/static/css/admin.css b/src/main/resources/static/css/admin.css new file mode 100644 index 00000000..a797f39b --- /dev/null +++ b/src/main/resources/static/css/admin.css @@ -0,0 +1,22 @@ +.nav .nav-link { + color: white; + border-color: white; +} + +.nav .nav-item { + margin: 0 5px; + flex: 1; +} + +.nav .nav-link.active { + color: black !important; +} + +.nav-tabs { + border-bottom: 0px; +} + +.separator { + border-bottom: 1px solid white; + margin: 10px 0; +} \ No newline at end of file diff --git a/src/main/resources/static/css/custom.css b/src/main/resources/static/css/custom.css index 1499a864..9d7cb489 100644 --- a/src/main/resources/static/css/custom.css +++ b/src/main/resources/static/css/custom.css @@ -66,4 +66,14 @@ footer { .prueba { font-weight: bold; +} + +.button-container { + display: flex; + justify-content: space-between; +} + +.button-container a { + flex: 1; + margin: 0 5px; } \ No newline at end of file diff --git a/src/main/resources/templates/fragments/head.html b/src/main/resources/templates/fragments/head.html index b75eb3c5..77172126 100644 --- a/src/main/resources/templates/fragments/head.html +++ b/src/main/resources/templates/fragments/head.html @@ -14,7 +14,7 @@ crossorigin="anonymous"> - + diff --git a/src/main/resources/templates/fragments/pagination.html b/src/main/resources/templates/fragments/pagination.html index ff816374..3a7fd539 100644 --- a/src/main/resources/templates/fragments/pagination.html +++ b/src/main/resources/templates/fragments/pagination.html @@ -2,7 +2,7 @@
  • - Primera + Primera
  • @@ -22,7 +22,7 @@
  • Última + th:href="@{'?page='+${page.getTotalPages()-1}}" th:text="#{page.last}"> Última
\ No newline at end of file diff --git a/src/main/resources/templates/fragments/paginationDynamic.html b/src/main/resources/templates/fragments/paginationDynamic.html new file mode 100644 index 00000000..7fb943c9 --- /dev/null +++ b/src/main/resources/templates/fragments/paginationDynamic.html @@ -0,0 +1,36 @@ +
+ + +
\ No newline at end of file diff --git a/src/main/resources/templates/player/admin/admin.html b/src/main/resources/templates/player/admin/admin.html new file mode 100644 index 00000000..27b2b915 --- /dev/null +++ b/src/main/resources/templates/player/admin/admin.html @@ -0,0 +1,54 @@ + + + + + + + + + + +
+

+ +
+
+
+
+
+ + + + diff --git a/src/main/resources/templates/player/admin/questionManagement.html b/src/main/resources/templates/player/admin/questionManagement.html new file mode 100644 index 00000000..1c9b64fb --- /dev/null +++ b/src/main/resources/templates/player/admin/questionManagement.html @@ -0,0 +1 @@ +

Preguntas

\ No newline at end of file diff --git a/src/main/resources/templates/player/admin/userManagement.html b/src/main/resources/templates/player/admin/userManagement.html new file mode 100644 index 00000000..0f723162 --- /dev/null +++ b/src/main/resources/templates/player/admin/userManagement.html @@ -0,0 +1,30 @@ +
+

+
+ + + + + + + + + + + + + + + + + +
UsernameEmailRoleActions
UsernameEmailRole
+
+
+
\ No newline at end of file diff --git a/src/main/resources/templates/player/home.html b/src/main/resources/templates/player/home.html index abf528c5..9de4e5cb 100644 --- a/src/main/resources/templates/player/home.html +++ b/src/main/resources/templates/player/home.html @@ -8,18 +8,15 @@

-

-
-
- -
-
- -
+ +
+ + +
From f8374a8815f515b35badd0bb9b5bd195364621e9 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 01:24:42 +0200 Subject: [PATCH 25/59] Added currency question --- .../static/JSON/QuestionTemplates.json | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/main/resources/static/JSON/QuestionTemplates.json b/src/main/resources/static/JSON/QuestionTemplates.json index 0fff93f2..cb0a2fc3 100644 --- a/src/main/resources/static/JSON/QuestionTemplates.json +++ b/src/main/resources/static/JSON/QuestionTemplates.json @@ -1,5 +1,6 @@ { "language_placeholder": "[LANGUAGE]", + "question_placeholder": "[QUESTION]", "categories": [ { "name": "Geography", @@ -9,26 +10,36 @@ "statements": [ { "language": "es", - "statement": "¿Cuál es la capital de [COUNTRY]?" + "statement": "¿Cuál es la capital de [QUESTION]?" }, { "language": "en", - "statement": "What is the capital of [COUNTRY]?" + "statement": "What is the capital of [QUESTION]?" }, { "language": "fr", - "statement": "Quelle est la capitale de [COUNTRY]?" + "statement": "Quelle est la capitale de [QUESTION]?" } ], - "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre capitales" + "sparqlQuery": "select distinct ?country ?countryLabel ?capital ?capitalLabel where {\n ?country wdt:P31 wd:Q6256 .\n ?capital wdt:P31 wd:Q5119 .\n ?country wdt:P36 ?capital .\n ?country rdfs:label ?countryLabel .\n ?capital rdfs:label ?capitalLabel .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?capitalLabel)=\"[LANGUAGE]\")\n }" }, { - "type": "border", - "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre fronteras" - }, - { - "type": "continent", - "sparqlQuery": "Consulta SPARQL para obtener preguntas sobre continentes" + "type": "currency", + "statements": [ + { + "language": "es", + "statement": "¿Cuál es la moneda de [QUESTION]?" + }, + { + "language": "en", + "statement": "What is the currency of [QUESTION]?" + }, + { + "language": "fr", + "statement": "Quelle est la monnaie de [QUESTION]?" + } + ], + "sparqlQuery": "select distinct ?country ?countryLabel ?currency ?currencyLabel where {\n ?country wdt:P31 wd:Q6256 .\n ?currency wdt:P31 wd:Q8142 .\n ?country wdt:P38 ?currency .\n ?country rdfs:label ?countryLabel .\n ?currency rdfs:label ?currencyLabel .\n FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240} .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?currencyLabel)=\"[LANGUAGE]\")\n }" } ] } From 11f09d33f0d6666d0f27b12e9eaceba4ef1a8cff Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 02:49:41 +0200 Subject: [PATCH 26/59] Initial implementation of the new question generator --- .../generators/QuestionGenerator.java | 4 -- .../generators/QuestionGeneratorV2.java | 48 +++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java diff --git a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java index ccaa4dab..7b552684 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java @@ -11,8 +11,4 @@ public interface QuestionGenerator { String getQuery(); List getQuestions(); - - Category getCategory(); - - } diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java new file mode 100644 index 00000000..00287cf7 --- /dev/null +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -0,0 +1,48 @@ +package com.uniovi.components.generators; + +import com.fasterxml.jackson.databind.JsonNode; +import com.uniovi.entities.Category; +import com.uniovi.entities.Question; + +import java.util.ArrayList; +import java.util.List; + +public class QuestionGeneratorV2 implements QuestionGenerator{ + + private JsonNode jsonNode; + private String language_placeholder; + private String question_placeholder; + private String language; + + public QuestionGeneratorV2(JsonNode jsonNode, String language) { + this.jsonNode = jsonNode; + this.language_placeholder = jsonNode.get("language_placeholder").textValue(); + this.question_placeholder = jsonNode.get("question_placeholder").textValue(); + this.language = language; + } + + @Override + public String getQuery() { + return null; + } + + @Override + public List getQuestions() { + List questions = new ArrayList<>(); + JsonNode categories = jsonNode.findValue("categories"); + for(JsonNode category : categories){ + String categoryName = category.get("name").textValue(); + Category cat = new Category(categoryName); + JsonNode questionsNode = category.findValue("questions"); + for(JsonNode question : questionsNode){ + questions.addAll(this.generateQuestion(question, cat)); + } + } + return questions; + } + + private List generateQuestion(JsonNode question, Category cat) { + String query = question.get("sparqlQuery").textValue(); + query = query.replace(language_placeholder, language); + } +} From e5a6f37607203ecfad6e7e6cde169670b31c6cee Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 03:00:08 +0200 Subject: [PATCH 27/59] First part of the request system --- .../generators/QuestionGeneratorV2.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index 00287cf7..1ff9cd60 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -1,9 +1,16 @@ package com.uniovi.components.generators; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.uniovi.entities.Category; import com.uniovi.entities.Question; +import java.net.URI; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -44,5 +51,53 @@ public List getQuestions() { private List generateQuestion(JsonNode question, Category cat) { String query = question.get("sparqlQuery").textValue(); query = query.replace(language_placeholder, language); + JsonNode results = getQueryResult(query); + + } + + private JsonNode getQueryResult(String query) { + + HttpClient client = HttpClient.newHttpClient(); + try { + + String endpointUrl = "https://query.wikidata.org/sparql?query=" + + URLEncoder.encode(this.getQuery(), StandardCharsets.UTF_8) + + "&format=json"; + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(endpointUrl)) + .header("Accept", "application/json") + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + // Process the JSON response using Jackson ObjectMapper + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonResponse = objectMapper.readTree(response.body()); + + // Access the data from the JSON response + JsonNode resultsNode = jsonResponse.path("results").path("bindings"); + + for (JsonNode result : resultsNode) { + + List options = this.generateOptions(resultsNode, result); + String correctAnswer = this.generateCorrectAnswer(result); + String questionStatement = this.getQuestionSubject(result); + + } + } catch (InterruptedException e) { + throw new QuestionGeneratorException("Generation of questions was interrupted"); + } catch (Exception e) { + throw new QuestionGeneratorException("An error occurred while generating questions"); + } + + return questions; + + } + + private static class QuestionGeneratorException extends RuntimeException { + public QuestionGeneratorException(String message) { + super(message); + } } } From 8a8ef292014d9b94140fe9ab62b1dd753800c779 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 03:13:01 +0200 Subject: [PATCH 28/59] Added question and answer placeholders to the JSON --- src/main/resources/static/JSON/QuestionTemplates.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/resources/static/JSON/QuestionTemplates.json b/src/main/resources/static/JSON/QuestionTemplates.json index cb0a2fc3..29df09ae 100644 --- a/src/main/resources/static/JSON/QuestionTemplates.json +++ b/src/main/resources/static/JSON/QuestionTemplates.json @@ -1,6 +1,7 @@ { "language_placeholder": "[LANGUAGE]", "question_placeholder": "[QUESTION]", + "answer_placeholder": "[ANSWER]", "categories": [ { "name": "Geography", @@ -21,7 +22,9 @@ "statement": "Quelle est la capitale de [QUESTION]?" } ], - "sparqlQuery": "select distinct ?country ?countryLabel ?capital ?capitalLabel where {\n ?country wdt:P31 wd:Q6256 .\n ?capital wdt:P31 wd:Q5119 .\n ?country wdt:P36 ?capital .\n ?country rdfs:label ?countryLabel .\n ?capital rdfs:label ?capitalLabel .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?capitalLabel)=\"[LANGUAGE]\")\n }" + "question": "countryLabel", + "answer": "capitalLabel", + "sparqlQuery": "select distinct ?country ?[QUESTION] ?capital ?[ANSWER] where {\n ?country wdt:P31 wd:Q6256 .\n ?capital wdt:P31 wd:Q5119 .\n ?country wdt:P36 ?capital .\n ?country rdfs:label ?countryLabel .\n ?capital rdfs:label ?capitalLabel .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?capitalLabel)=\"[LANGUAGE]\")\n }" }, { "type": "currency", @@ -39,7 +42,9 @@ "statement": "Quelle est la monnaie de [QUESTION]?" } ], - "sparqlQuery": "select distinct ?country ?countryLabel ?currency ?currencyLabel where {\n ?country wdt:P31 wd:Q6256 .\n ?currency wdt:P31 wd:Q8142 .\n ?country wdt:P38 ?currency .\n ?country rdfs:label ?countryLabel .\n ?currency rdfs:label ?currencyLabel .\n FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240} .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?currencyLabel)=\"[LANGUAGE]\")\n }" + "question": "countryLabel", + "answer": "currencyLabel", + "sparqlQuery": "select distinct ?country ?[QUESTION] ?currency ?[ANSWER] where {\n ?country wdt:P31 wd:Q6256 .\n ?currency wdt:P31 wd:Q8142 .\n ?country wdt:P38 ?currency .\n ?country rdfs:label ?countryLabel .\n ?currency rdfs:label ?currencyLabel .\n FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240} .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?currencyLabel)=\"[LANGUAGE]\")\n }" } ] } From e3191167f0a8955b0166830c2d9f0a62ead50c1d Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 03:30:13 +0200 Subject: [PATCH 29/59] Added statement generation based on language --- .../generators/QuestionGeneratorV2.java | 47 +++++++++++++++---- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index 1ff9cd60..c03e7386 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -19,12 +19,14 @@ public class QuestionGeneratorV2 implements QuestionGenerator{ private JsonNode jsonNode; private String language_placeholder; private String question_placeholder; + private String answer_placeholder; private String language; public QuestionGeneratorV2(JsonNode jsonNode, String language) { this.jsonNode = jsonNode; this.language_placeholder = jsonNode.get("language_placeholder").textValue(); this.question_placeholder = jsonNode.get("question_placeholder").textValue(); + this.answer_placeholder = jsonNode.get("answer_placeholder").textValue(); this.language = language; } @@ -49,15 +51,47 @@ public List getQuestions() { } private List generateQuestion(JsonNode question, Category cat) { + // Get the SPARQL query from the JSON String query = question.get("sparqlQuery").textValue(); - query = query.replace(language_placeholder, language); + // Replace the placeholders in the query with the actual values + query = query.replace(language_placeholder, language). + replace(question_placeholder, question.get("question").textValue()). + replace(answer_placeholder, question.get("answer").textValue()); + // Execute the query and get the results JsonNode results = getQueryResult(query); + List questions = new ArrayList<>(); + // Prepare the statement base based on the language + String statement = this.prepareStatement(question); + for(JsonNode result : results){ + String statement = result.get("statement").textValue(); + List options = new ArrayList<>(); + for(JsonNode option : result.get("options")){ + options.add(option.textValue()); + } + String correctAnswer = result.get("correctAnswer").textValue(); + this.questionGenerator(statement, options, correctAnswer, cat, questions); + } + } + /** + * Generates a statement based on the language of the question + * @param question The question node + * @return The statement in the language of the question or null if the language is not found + */ + private String prepareStatement(JsonNode question) { + JsonNode statementNode = question.findValue("statements"); + for (JsonNode statement : statementNode) { + if (statement.get("language").textValue().equals(language)) { + return statement.get("statement").textValue(); + } + } + return null; } private JsonNode getQueryResult(String query) { HttpClient client = HttpClient.newHttpClient(); + JsonNode resultsNode; try { String endpointUrl = "https://query.wikidata.org/sparql?query=" + @@ -76,22 +110,15 @@ private JsonNode getQueryResult(String query) { JsonNode jsonResponse = objectMapper.readTree(response.body()); // Access the data from the JSON response - JsonNode resultsNode = jsonResponse.path("results").path("bindings"); - - for (JsonNode result : resultsNode) { - - List options = this.generateOptions(resultsNode, result); - String correctAnswer = this.generateCorrectAnswer(result); - String questionStatement = this.getQuestionSubject(result); + resultsNode = jsonResponse.path("results").path("bindings"); - } } catch (InterruptedException e) { throw new QuestionGeneratorException("Generation of questions was interrupted"); } catch (Exception e) { throw new QuestionGeneratorException("An error occurred while generating questions"); } - return questions; + return resultsNode; } From 28e106839812dece6d79bf4b65b1866ded3e7bb3 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 03:49:28 +0200 Subject: [PATCH 30/59] First version of the question generator finished --- .../generators/QuestionGeneratorV2.java | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index c03e7386..8b7d39c8 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.uniovi.entities.Answer; import com.uniovi.entities.Category; import com.uniovi.entities.Question; @@ -53,24 +54,50 @@ public List getQuestions() { private List generateQuestion(JsonNode question, Category cat) { // Get the SPARQL query from the JSON String query = question.get("sparqlQuery").textValue(); + + // Get the question and answer words from the JSON + String questionLabel = question.get("question").textValue(); + String answerLabel= question.get("answer").textValue(); + // Replace the placeholders in the query with the actual values query = query.replace(language_placeholder, language). - replace(question_placeholder, question.get("question").textValue()). - replace(answer_placeholder, question.get("answer").textValue()); + replace(question_placeholder, questionLabel). + replace(answer_placeholder, answerLabel); + // Execute the query and get the results JsonNode results = getQueryResult(query); List questions = new ArrayList<>(); + // Prepare the statement base based on the language String statement = this.prepareStatement(question); - for(JsonNode result : results){ - String statement = result.get("statement").textValue(); - List options = new ArrayList<>(); - for(JsonNode option : result.get("options")){ - options.add(option.textValue()); + + for (JsonNode result : results) { + // Generate the correct answer + String correctAnswer = result.get(answerLabel).textValue(); + Answer correct = new Answer(correctAnswer, true); + + // Generate the options + List options = this.generateOptions(results, correctAnswer, answerLabel); + + + // Generate the question statement + String questionStatement = statement.replace(question_placeholder, result.get(questionLabel).textValue()); + + // Generate the question + questions.add(new Question(questionStatement, options, correct, cat, language)); + } + return questions; + } + + private List generateOptions(JsonNode results, String correctAnswer, String answerLabel) { + List options = new ArrayList<>(); + for (JsonNode result : results) { + String option = result.get(answerLabel).textValue(); + if (!option.equals(correctAnswer)) { + options.add(new Answer(option, false)); } - String correctAnswer = result.get("correctAnswer").textValue(); - this.questionGenerator(statement, options, correctAnswer, cat, questions); } + return options; } /** From b812a5f8af316cb099c7ee2ecef48cf15029af11 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 03:56:04 +0200 Subject: [PATCH 31/59] Added name only constructor for category --- src/main/java/com/uniovi/entities/Category.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/uniovi/entities/Category.java b/src/main/java/com/uniovi/entities/Category.java index c368e762..dcfa19fc 100644 --- a/src/main/java/com/uniovi/entities/Category.java +++ b/src/main/java/com/uniovi/entities/Category.java @@ -33,6 +33,10 @@ public Category(String name, String description) { this.description = description; } + public Category(String categoryName) { + this.name = categoryName; + } + @Override public String toString() { return name; From a079a2116ad51d048108a370d276349576a0b676 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 04:19:00 +0200 Subject: [PATCH 32/59] Removed old templates --- .../generators/AbstractQuestionGenerator.java | 97 ------------------- .../generators/art/AbstractArtGenerator.java | 17 ---- .../art/ArtMovementQuestionGenerator.java | 74 -------------- .../art/ArtPeriodQuestionGenerator.java | 74 -------------- .../art/ArtStyleQuestionGenerator.java | 74 -------------- .../art/ArtWorkQuestionGenerator.java | 76 --------------- .../geography/AbstractGeographyGenerator.java | 17 ---- .../geography/AreaQuestionGenerator.java | 52 ---------- .../geography/BorderQuestionGenerator.java | 76 --------------- .../geography/CapitalQuestionGenerator.java | 77 --------------- .../ContinentQuestionGeneration.java | 76 --------------- .../geography/CurrencyQuestionGenerator.java | 76 --------------- .../geography/LanguageQuestionGenerator.java | 76 --------------- .../PopulationQuestionGenerator.java | 52 ---------- .../history/AbstractHistoryGenerator.java | 17 ---- .../HistoricalArtifactQuestionGeneration.java | 75 -------------- .../HistoricalBattleQuestionGeneration.java | 75 -------------- .../HistoricalDynastyQuestionGeneration.java | 75 -------------- .../HistoricalEventQuestionGeneration.java | 75 -------------- ...HistoricalInventionQuestionGeneration.java | 75 -------------- .../HistoricalLeaderQuestionGeneration.java | 75 -------------- .../HistoricalPeriodQuestionGeneration.java | 75 -------------- .../movie/AbstractMovieGenerator.java | 17 ---- .../movie/MovieDirectorQuestionGenerator.java | 75 -------------- .../movie/MovieGenreQuestionGenerator.java | 74 -------------- .../MovieReleaseYearQuestionGenerator.java | 75 -------------- .../movie/OriginalTitleQuestionGenerator.java | 74 -------------- .../science/AbstractScienceGenerator.java | 17 ---- .../MathPhysicsFormulaQuestionGenerator.java | 74 -------------- ...cientificAchievementQuestionGenerator.java | 75 -------------- .../ScientificDiscoveryQuestionGenerator.java | 75 -------------- .../ScientistBirthplaceQuestionGenerator.java | 75 -------------- 32 files changed, 2087 deletions(-) delete mode 100644 src/main/java/com/uniovi/components/generators/AbstractQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/AbstractGeographyGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/BorderQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/CapitalQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/ContinentQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java delete mode 100644 src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java delete mode 100644 src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/generators/AbstractQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/AbstractQuestionGenerator.java deleted file mode 100644 index 7c534d91..00000000 --- a/src/main/java/com/uniovi/components/generators/AbstractQuestionGenerator.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.uniovi.components.generators; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.uniovi.entities.Answer; -import com.uniovi.entities.Category; -import com.uniovi.entities.Question; -import com.uniovi.services.CategoryService; -import java.net.URI; -import java.net.URLEncoder; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public abstract class AbstractQuestionGenerator implements QuestionGenerator{ - private List questions = new ArrayList<>(); - protected final CategoryService categoryService; - - protected Random random = new Random(); - - protected String statement; - protected String language; - - protected AbstractQuestionGenerator(CategoryService categoryService) { - this.categoryService = categoryService; - } - - public void questionGenerator(String statement, List options, String correctAnswer, Category category){ - List answers = new ArrayList<>(); - //Generamos las respuestas y las añadimos a la lista - for(String s: options){ - Answer answer = new Answer(s, false); - answers.add(answer); - } - //Generamos la respuesta correcta y la añadimos a la lista - Answer correct = new Answer(correctAnswer, true); - answers.add(correct); - - Question question = new Question(statement, answers, correct, category, language); - question.scrambleOptions(); - questions.add(question); - } - - public List getQuestions() { - HttpClient client = HttpClient.newHttpClient(); - try { - - String endpointUrl = "https://query.wikidata.org/sparql?query=" + - URLEncoder.encode(this.getQuery(), StandardCharsets.UTF_8) + - "&format=json"; - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(endpointUrl)) - .header("Accept", "application/json") - .build(); - - HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - - // Process the JSON response using Jackson ObjectMapper - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonResponse = objectMapper.readTree(response.body()); - - // Access the data from the JSON response - JsonNode resultsNode = jsonResponse.path("results").path("bindings"); - - for (JsonNode result : resultsNode) { - - List options = this.generateOptions(resultsNode, result); - String correctAnswer = this.generateCorrectAnswer(result); - String questionStatement = this.getQuestionSubject(result); - questionGenerator(questionStatement, options, correctAnswer, this.getCategory()); - - } - } catch (InterruptedException e) { - throw new QuestionGeneratorException("Generation of questions was interrupted"); - } catch (Exception e) { - throw new QuestionGeneratorException("An error occurred while generating questions"); - } - - return questions; - } - - protected abstract List generateOptions(JsonNode results, JsonNode result); - protected abstract String generateCorrectAnswer(JsonNode result); - - protected abstract String getQuestionSubject(JsonNode result); - - private static class QuestionGeneratorException extends RuntimeException { - public QuestionGeneratorException(String message) { - super(message); - } - } -} diff --git a/src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java b/src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java deleted file mode 100644 index 8d0999ef..00000000 --- a/src/main/java/com/uniovi/components/generators/art/AbstractArtGenerator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.uniovi.components.generators.art; - -import com.uniovi.components.generators.AbstractQuestionGenerator; -import com.uniovi.entities.Category; -import com.uniovi.services.CategoryService; - -public abstract class AbstractArtGenerator extends AbstractQuestionGenerator { - - protected AbstractArtGenerator(CategoryService categoryService) { - super(categoryService); - } - - @Override - public Category getCategory() { - return categoryService.getCategoryByName("Art"); - } -} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java deleted file mode 100644 index 81fef3cd..00000000 --- a/src/main/java/com/uniovi/components/generators/art/ArtMovementQuestionGenerator.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.uniovi.components.generators.art; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ArtMovementQuestionGenerator extends AbstractArtGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which art movement is associated with "); - put("es", "¿Con qué movimiento artístico se asocia "); - put("fr", "Quel mouvement artistique est associé à "); - } - }; - - public ArtMovementQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?movement ?movementLabel\n" + - "WHERE {" + - " ?movement wdt:P31 wd:Q968159 ." + // Instance of Art movement - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllMovements(JsonNode resultsNode, String correctMovement) { - List allMovements = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String movement = result.path("movementLabel").path("value").asText(); - if (!movement.equals(correctMovement)) { - allMovements.add(movement); - } - } - return allMovements; - } - - private List selectRandomIncorrectMovements(List allMovements, String correctMovement, int count) { - List incorrectMovements = new ArrayList<>(); - while (incorrectMovements.size() < count && allMovements.size() > 0) { - int randomIndex = random.nextInt(allMovements.size()); - String selectedMovement = allMovements.remove(randomIndex); - if (!selectedMovement.equals(correctMovement) && !incorrectMovements.contains(selectedMovement)) { - incorrectMovements.add(selectedMovement); - } - } - return incorrectMovements; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String movementLabel = result.path("movementLabel").path("value").asText(); - return selectRandomIncorrectMovements(getAllMovements(results, movementLabel), movementLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("movementLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("movementLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java deleted file mode 100644 index e005d262..00000000 --- a/src/main/java/com/uniovi/components/generators/art/ArtPeriodQuestionGenerator.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.uniovi.components.generators.art; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ArtPeriodQuestionGenerator extends AbstractArtGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which art period is associated with "); - put("es", "¿Con qué período artístico se asocia "); - put("fr", "Quelle période artistique est associée à "); - } - }; - - public ArtPeriodQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?period ?periodLabel\n" + - "WHERE {" + - " ?period wdt:P31 wd:Q187437 ." + // Instance of Art period - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllPeriods(JsonNode resultsNode, String correctPeriod) { - List allPeriods = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String period = result.path("periodLabel").path("value").asText(); - if (!period.equals(correctPeriod)) { - allPeriods.add(period); - } - } - return allPeriods; - } - - private List selectRandomIncorrectPeriods(List allPeriods, String correctPeriod, int count) { - List incorrectPeriods = new ArrayList<>(); - while (incorrectPeriods.size() < count && allPeriods.size() > 0) { - int randomIndex = random.nextInt(allPeriods.size()); - String selectedPeriod = allPeriods.remove(randomIndex); - if (!selectedPeriod.equals(correctPeriod) && !incorrectPeriods.contains(selectedPeriod)) { - incorrectPeriods.add(selectedPeriod); - } - } - return incorrectPeriods; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String periodLabel = result.path("periodLabel").path("value").asText(); - return selectRandomIncorrectPeriods(getAllPeriods(results, periodLabel), periodLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("periodLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("periodLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java deleted file mode 100644 index e347e643..00000000 --- a/src/main/java/com/uniovi/components/generators/art/ArtStyleQuestionGenerator.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.uniovi.components.generators.art; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ArtStyleQuestionGenerator extends AbstractArtGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which art style is associated with "); - put("es", "¿Con qué estilo artístico se asocia "); - put("fr", "Quel style artistique est associé à "); - } - }; - - public ArtStyleQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?style ?styleLabel\n" + - "WHERE {" + - " ?style wdt:P31 wd:Q179337 ." + // Instance of Art style - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllStyles(JsonNode resultsNode, String correctStyle) { - List allStyles = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String style = result.path("styleLabel").path("value").asText(); - if (!style.equals(correctStyle)) { - allStyles.add(style); - } - } - return allStyles; - } - - private List selectRandomIncorrectStyles(List allStyles, String correctStyle, int count) { - List incorrectStyles = new ArrayList<>(); - while (incorrectStyles.size() < count && allStyles.size() > 0) { - int randomIndex = random.nextInt(allStyles.size()); - String selectedStyle = allStyles.remove(randomIndex); - if (!selectedStyle.equals(correctStyle) && !incorrectStyles.contains(selectedStyle)) { - incorrectStyles.add(selectedStyle); - } - } - return incorrectStyles; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String styleLabel = result.path("styleLabel").path("value").asText(); - return selectRandomIncorrectStyles(getAllStyles(results, styleLabel), styleLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("styleLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("styleLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java deleted file mode 100644 index 68f95d23..00000000 --- a/src/main/java/com/uniovi/components/generators/art/ArtWorkQuestionGenerator.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.uniovi.components.generators.art; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ArtWorkQuestionGenerator extends AbstractArtGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Who created the artwork "); - put("es", "¿Quién creó la obra de arte "); - put("fr", "Qui a créé l'œuvre d'art "); - } - }; - - public ArtWorkQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?artist ?artistLabel ?artwork ?artworkLabel\n" + - "WHERE {" + - " ?artist wdt:P31 wd:Q5 ." + // Instance of Human - " ?artwork wdt:P31 wd:Q3305213 ." + // Instance of Artwork - " ?artwork wdt:P170 ?artist ." + // Creator - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllArtworks(JsonNode resultsNode, String correctArtwork) { - List allArtworks = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String artwork = result.path("artworkLabel").path("value").asText(); - if (!artwork.equals(correctArtwork)) { - allArtworks.add(artwork); - } - } - return allArtworks; - } - - private List selectRandomIncorrectArtworks(List allArtworks, String correctArtwork, int count) { - List incorrectArtworks = new ArrayList<>(); - while (incorrectArtworks.size() < count && allArtworks.size() > 0) { - int randomIndex = random.nextInt(allArtworks.size()); - String selectedArtwork = allArtworks.remove(randomIndex); - if (!selectedArtwork.equals(correctArtwork) && !incorrectArtworks.contains(selectedArtwork)) { - incorrectArtworks.add(selectedArtwork); - } - } - return incorrectArtworks; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String artworkLabel = result.path("artworkLabel").path("value").asText(); - return selectRandomIncorrectArtworks(getAllArtworks(results, artworkLabel), artworkLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("artistLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("artworkLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/AbstractGeographyGenerator.java b/src/main/java/com/uniovi/components/generators/geography/AbstractGeographyGenerator.java deleted file mode 100644 index d01919e9..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/AbstractGeographyGenerator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.uniovi.components.generators.AbstractQuestionGenerator; -import com.uniovi.entities.Category; -import com.uniovi.services.CategoryService; - -public abstract class AbstractGeographyGenerator extends AbstractQuestionGenerator { - - protected AbstractGeographyGenerator(CategoryService categoryService) { - super(categoryService); - } - - @Override - public Category getCategory() { - return categoryService.getCategoryByName("Geography"); - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java deleted file mode 100644 index d69d2edd..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/AreaQuestionGenerator.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.*; - -public class AreaQuestionGenerator extends AbstractGeographyGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What is the area of "); - put("es", "¿Cuál es el área de "); - put("fr", "Quelle est la superficie de "); - } - }; - - public AreaQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?country ?countryLabel ?area\n" + - "WHERE {" + - " ?country wdt:P31 wd:Q3624078 ." + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + - " ?country wdt:P2046 ?area ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - // Este generador de preguntas no necesita opciones, ya que la respuesta correcta es el área. - return Collections.emptyList(); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("area").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("countryLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/BorderQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/BorderQuestionGenerator.java deleted file mode 100644 index 81d5cdb0..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/BorderQuestionGenerator.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; - -import java.util.*; - -public class BorderQuestionGenerator extends AbstractGeographyGenerator{ - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which countries share a border with "); - put("es", "¿Con qué países comparte frontera "); - put("fr", "Avec quels pays partage-t-il une frontière "); - } - }; - private Set usedCountries = new HashSet<>(); - - public BorderQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllBorderingCountries(JsonNode resultsNode, String correctCountry) { - List allBorderingCountries = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String borderingCountry = result.path("borderingCountryLabel").path("value").asText(); - if (!borderingCountry.equals(correctCountry)) { - allBorderingCountries.add(borderingCountry); - } - } - return allBorderingCountries; - } - - private List selectRandomIncorrectBorderingCountries(List allBorderingCountries, String correctCountry, int count) { - List incorrectBorderingCountries = new ArrayList<>(); - while (incorrectBorderingCountries.size() < count && allBorderingCountries.size() > 0) { - int randomIndex = random.nextInt(allBorderingCountries.size()); - String selectedBorderingCountry = allBorderingCountries.remove(randomIndex); - if (!selectedBorderingCountry.equals(correctCountry) && !incorrectBorderingCountries.contains(selectedBorderingCountry)) { - incorrectBorderingCountries.add(selectedBorderingCountry); - } - } - return incorrectBorderingCountries; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String borderingCountryLabel = result.path("borderingCountryLabel").path("value").asText(); - return selectRandomIncorrectBorderingCountries( - getAllBorderingCountries(results, borderingCountryLabel), - borderingCountryLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("borderingCountryLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("countryLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?country ?countryLabel ?borderingCountry ?borderingCountryLabel\n" + - "WHERE {" + - " ?country wdt:P31 wd:Q3624078 ." + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + - " ?country wdt:P47 ?borderingCountry ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/CapitalQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/CapitalQuestionGenerator.java deleted file mode 100644 index 199d4dc5..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/CapitalQuestionGenerator.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.*; - -public class CapitalQuestionGenerator extends AbstractGeographyGenerator{ - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What is the capital of "); - put("es", "¿Cuál es la capital de "); - put("fr", "Quelle est la capitale de "); - } - }; - - public CapitalQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?country ?countryLabel ?capital ?capitalLabel\n" + - "WHERE {" + - " ?country wdt:P31 wd:Q3624078 ." + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + - " OPTIONAL { ?country wdt:P36 ?capital } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?countryLabel"; - } - - private List getAllCapitals(JsonNode resultsNode, String correctCapital) { - // Obtener todas las capitales del JSON (distintas a la capital correcta) - List allCapitals = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String capital = result.path("capitalLabel").path("value").asText(); - if (!capital.equals(correctCapital)) { - allCapitals.add(capital); - } - } - return allCapitals; - } - - private List selectRandomIncorrectCapitals(List allCapitals, String correctCapital, int count) { - List incorrectCapitals = new ArrayList<>(); - while (incorrectCapitals.size() < count && allCapitals.size() > 0) { - int randomIndex = random.nextInt(allCapitals.size()); - String selectedCapital = allCapitals.remove(randomIndex); - if (!selectedCapital.equals(correctCapital) && !incorrectCapitals.contains(selectedCapital)) { - incorrectCapitals.add(selectedCapital); - } - } - return incorrectCapitals; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String capitalLabel = result.path("capitalLabel").path("value").asText(); - return selectRandomIncorrectCapitals(getAllCapitals(results, capitalLabel), capitalLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("capitalLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("countryLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/ContinentQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/geography/ContinentQuestionGeneration.java deleted file mode 100644 index dec77dc0..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/ContinentQuestionGeneration.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class ContinentQuestionGeneration extends AbstractGeographyGenerator{ - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "In which continent is "); - put("es", "¿En qué continente se encuentra "); - put("fr", "Sur quel continent est-il situé "); - } - }; - - public ContinentQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllContinents(JsonNode resultsNode, String correctContinent) { - // Obtener todas las capitales del JSON (distintas a la capital correcta) - List allContinents = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String continent = result.path("continentLabel").path("value").asText(); - if (!continent.equals(correctContinent)) { - allContinents.add(continent); - } - } - return allContinents; - } - - private List selectRandomIncorrectContinents(List allContinents, String correctContinent, int count) { - List incorrectContinents = new ArrayList<>(); - while (incorrectContinents.size() < count && allContinents.size() > 0) { - int randomIndex = random.nextInt(allContinents.size()); - String selectedCapital = allContinents.remove(randomIndex); - if (!selectedCapital.equals(correctContinent) && !incorrectContinents.contains(selectedCapital)) { - incorrectContinents.add(selectedCapital); - } - } - return incorrectContinents; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String continentLabel = result.path("continentLabel").path("value").asText(); - return selectRandomIncorrectContinents(getAllContinents(results, continentLabel), continentLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("continentLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("countryLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?country ?countryLabel ?continent ?continentLabel\n" + - "WHERE {" + - " ?country wdt:P31 wd:Q3624078 " + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + - " OPTIONAL { ?country wdt:P30 ?continent } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?countryLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java deleted file mode 100644 index 14bda93f..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/CurrencyQuestionGenerator.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.*; - -public class CurrencyQuestionGenerator extends AbstractGeographyGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What is the currency of "); - put("es", "¿Cuál es la moneda de "); - put("fr", "Quelle est la monnaie de "); - } - }; - - public CurrencyQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?country ?countryLabel ?currency ?currencyLabel\n" + - "WHERE {" + - " ?country wdt:P31 wd:Q3624078 ." + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + - " ?country wdt:P38 ?currency ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllCurrencies(JsonNode resultsNode, String correctCurrency) { - // Obtener todas las monedas del JSON (distintas a la moneda correcta) - List allCurrencies = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String currency = result.path("currencyLabel").path("value").asText(); - if (!currency.equals(correctCurrency)) { - allCurrencies.add(currency); - } - } - return allCurrencies; - } - - private List selectRandomIncorrectCurrencies(List allCurrencies, String correctCurrency, int count) { - List incorrectCurrencies = new ArrayList<>(); - while (incorrectCurrencies.size() < count && allCurrencies.size() > 0) { - int randomIndex = random.nextInt(allCurrencies.size()); - String selectedCurrency = allCurrencies.remove(randomIndex); - if (!selectedCurrency.equals(correctCurrency) && !incorrectCurrencies.contains(selectedCurrency)) { - incorrectCurrencies.add(selectedCurrency); - } - } - return incorrectCurrencies; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String currencyLabel = result.path("currencyLabel").path("value").asText(); - return selectRandomIncorrectCurrencies(getAllCurrencies(results, currencyLabel), currencyLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("currencyLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("countryLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java deleted file mode 100644 index b1bf363a..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/LanguageQuestionGenerator.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.*; - -public class LanguageQuestionGenerator extends AbstractGeographyGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What is the official language of "); - put("es", "¿Cuál es el idioma oficial de "); - put("fr", "Quelle est la langue officielle de "); - } - }; - - public LanguageQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?country ?countryLabel ?language ?languageLabel\n" + - "WHERE {" + - " ?country wdt:P31 wd:Q3624078 ." + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + - " ?country wdt:P37 ?language ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllLanguages(JsonNode resultsNode, String correctLanguage) { - // Obtener todos los idiomas del JSON (distintos al idioma correcto) - List allLanguages = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String language = result.path("languageLabel").path("value").asText(); - if (!language.equals(correctLanguage)) { - allLanguages.add(language); - } - } - return allLanguages; - } - - private List selectRandomIncorrectLanguages(List allLanguages, String correctLanguage, int count) { - List incorrectLanguages = new ArrayList<>(); - while (incorrectLanguages.size() < count && allLanguages.size() > 0) { - int randomIndex = random.nextInt(allLanguages.size()); - String selectedLanguage = allLanguages.remove(randomIndex); - if (!selectedLanguage.equals(correctLanguage) && !incorrectLanguages.contains(selectedLanguage)) { - incorrectLanguages.add(selectedLanguage); - } - } - return incorrectLanguages; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String languageLabel = result.path("languageLabel").path("value").asText(); - return selectRandomIncorrectLanguages(getAllLanguages(results, languageLabel), languageLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("languageLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("countryLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java deleted file mode 100644 index e0df4901..00000000 --- a/src/main/java/com/uniovi/components/generators/geography/PopulationQuestionGenerator.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.uniovi.components.generators.geography; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.*; - -public class PopulationQuestionGenerator extends AbstractGeographyGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What is the population of "); - put("es", "¿Cuál es la población de "); - put("fr", "Quelle est la population de "); - } - }; - - public PopulationQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?country ?countryLabel ?population\n" + - "WHERE {" + - " ?country wdt:P31 wd:Q3624078 ." + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240}" + - " FILTER NOT EXISTS {?country wdt:P31 wd:Q28171280}" + - " ?country wdt:P1082 ?population ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - // Este generador de preguntas no necesita opciones, ya que la respuesta correcta es la población. - return Collections.emptyList(); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("population").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("countryLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java b/src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java deleted file mode 100644 index da8d870b..00000000 --- a/src/main/java/com/uniovi/components/generators/history/AbstractHistoryGenerator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.uniovi.components.generators.AbstractQuestionGenerator; -import com.uniovi.entities.Category; -import com.uniovi.services.CategoryService; - -public abstract class AbstractHistoryGenerator extends AbstractQuestionGenerator { - - protected AbstractHistoryGenerator(CategoryService categoryService) { - super(categoryService); - } - - @Override - public Category getCategory() { - return categoryService.getCategoryByName("History"); - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java deleted file mode 100644 index 0bb30abf..00000000 --- a/src/main/java/com/uniovi/components/generators/history/HistoricalArtifactQuestionGeneration.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class HistoricalArtifactQuestionGeneration extends AbstractHistoryGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which historical artifact is associated with "); - put("es", "¿Con qué artefacto histórico se asocia "); - put("fr", "Quel artefact historique est associé à "); - } - }; - - public HistoricalArtifactQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllArtifacts(JsonNode resultsNode, String correctArtifact) { - // Obtaining all historical artifacts from the JSON (different from the correct artifact) - List allArtifacts = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String artifact = result.path("artifactLabel").path("value").asText(); - if (!artifact.equals(correctArtifact)) { - allArtifacts.add(artifact); - } - } - return allArtifacts; - } - - private List selectRandomIncorrectArtifacts(List allArtifacts, String correctArtifact, int count) { - List incorrectArtifacts = new ArrayList<>(); - while (incorrectArtifacts.size() < count && allArtifacts.size() > 0) { - int randomIndex = random.nextInt(allArtifacts.size()); - String selectedArtifact = allArtifacts.remove(randomIndex); - if (!selectedArtifact.equals(correctArtifact) && !incorrectArtifacts.contains(selectedArtifact)) { - incorrectArtifacts.add(selectedArtifact); - } - } - return incorrectArtifacts; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String artifactLabel = result.path("artifactLabel").path("value").asText(); - return selectRandomIncorrectArtifacts(getAllArtifacts(results, artifactLabel), artifactLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("artifactLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?artifact ?artifactLabel ?historicalEvent ?historicalEventLabel\n" + - "WHERE {" + - " ?artifact wdt:P31 wd:Q5314 ." + - " ?historicalEvent wdt:P31 wd:Q198 ." + - " OPTIONAL { ?artifact wdt:P1080 ?historicalEvent } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?artifactLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java deleted file mode 100644 index 5c83c79c..00000000 --- a/src/main/java/com/uniovi/components/generators/history/HistoricalBattleQuestionGeneration.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class HistoricalBattleQuestionGeneration extends AbstractHistoryGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which historical battle is associated with "); - put("es", "¿Con qué batalla histórica se asocia "); - put("fr", "Quelle bataille historique est associée à "); - } - }; - - public HistoricalBattleQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllBattles(JsonNode resultsNode, String correctBattle) { - // Obtaining all historical battles from the JSON (different from the correct battle) - List allBattles = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String battle = result.path("battleLabel").path("value").asText(); - if (!battle.equals(correctBattle)) { - allBattles.add(battle); - } - } - return allBattles; - } - - private List selectRandomIncorrectBattles(List allBattles, String correctBattle, int count) { - List incorrectBattles = new ArrayList<>(); - while (incorrectBattles.size() < count && allBattles.size() > 0) { - int randomIndex = random.nextInt(allBattles.size()); - String selectedBattle = allBattles.remove(randomIndex); - if (!selectedBattle.equals(correctBattle) && !incorrectBattles.contains(selectedBattle)) { - incorrectBattles.add(selectedBattle); - } - } - return incorrectBattles; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String battleLabel = result.path("battleLabel").path("value").asText(); - return selectRandomIncorrectBattles(getAllBattles(results, battleLabel), battleLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("battleLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?battle ?battleLabel ?historicalEvent ?historicalEventLabel\n" + - "WHERE {" + - " ?battle wdt:P31 wd:Q178561 ." + - " ?historicalEvent wdt:P31 wd:Q198 ." + - " OPTIONAL { ?battle wdt:P361 ?historicalEvent } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?battleLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java deleted file mode 100644 index 7f65f88e..00000000 --- a/src/main/java/com/uniovi/components/generators/history/HistoricalDynastyQuestionGeneration.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class HistoricalDynastyQuestionGeneration extends AbstractHistoryGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which historical dynasty is associated with "); - put("es", "¿Con qué dinastía histórica se asocia "); - put("fr", "Quelle dynastie historique est associée à "); - } - }; - - public HistoricalDynastyQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllDynasties(JsonNode resultsNode, String correctDynasty) { - // Obtaining all historical dynasties from the JSON (different from the correct dynasty) - List allDynasties = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String dynasty = result.path("dynastyLabel").path("value").asText(); - if (!dynasty.equals(correctDynasty)) { - allDynasties.add(dynasty); - } - } - return allDynasties; - } - - private List selectRandomIncorrectDynasties(List allDynasties, String correctDynasty, int count) { - List incorrectDynasties = new ArrayList<>(); - while (incorrectDynasties.size() < count && allDynasties.size() > 0) { - int randomIndex = random.nextInt(allDynasties.size()); - String selectedDynasty = allDynasties.remove(randomIndex); - if (!selectedDynasty.equals(correctDynasty) && !incorrectDynasties.contains(selectedDynasty)) { - incorrectDynasties.add(selectedDynasty); - } - } - return incorrectDynasties; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String dynastyLabel = result.path("dynastyLabel").path("value").asText(); - return selectRandomIncorrectDynasties(getAllDynasties(results, dynastyLabel), dynastyLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("dynastyLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?dynasty ?dynastyLabel ?historicalEvent ?historicalEventLabel\n" + - "WHERE {" + - " ?dynasty wdt:P31 wd:Q11410 ." + - " ?historicalEvent wdt:P31 wd:Q198 ." + - " OPTIONAL { ?dynasty wdt:P108 ?historicalEvent } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?dynastyLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java deleted file mode 100644 index cede3058..00000000 --- a/src/main/java/com/uniovi/components/generators/history/HistoricalEventQuestionGeneration.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class HistoricalEventQuestionGeneration extends AbstractHistoryGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "In what historical event did "); - put("es", "¿En qué evento histórico participó "); - put("fr", "Dans quel événement historique a participé "); - } - }; - - public HistoricalEventQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllEvents(JsonNode resultsNode, String correctEvent) { - // Obtener todos los eventos históricos del JSON (diferentes al evento correcto) - List allEvents = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String event = result.path("eventLabel").path("value").asText(); - if (!event.equals(correctEvent)) { - allEvents.add(event); - } - } - return allEvents; - } - - private List selectRandomIncorrectEvents(List allEvents, String correctEvent, int count) { - List incorrectEvents = new ArrayList<>(); - while (incorrectEvents.size() < count && allEvents.size() > 0) { - int randomIndex = random.nextInt(allEvents.size()); - String selectedEvent = allEvents.remove(randomIndex); - if (!selectedEvent.equals(correctEvent) && !incorrectEvents.contains(selectedEvent)) { - incorrectEvents.add(selectedEvent); - } - } - return incorrectEvents; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String eventLabel = result.path("eventLabel").path("value").asText(); - return selectRandomIncorrectEvents(getAllEvents(results, eventLabel), eventLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("eventLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("personLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?person ?personLabel ?event ?eventLabel\n" + - "WHERE {" + - " ?person wdt:P31 wd:Q5 ." + - " ?event wdt:P31 wd:Q198 ." + - " OPTIONAL { ?person wdt:P106 ?event } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?personLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java deleted file mode 100644 index 01af421d..00000000 --- a/src/main/java/com/uniovi/components/generators/history/HistoricalInventionQuestionGeneration.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class HistoricalInventionQuestionGeneration extends AbstractHistoryGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which historical invention is associated with "); - put("es", "¿Con qué invención histórica se asocia "); - put("fr", "Quelle invention historique est associée à "); - } - }; - - public HistoricalInventionQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllInventions(JsonNode resultsNode, String correctInvention) { - // Obtaining all historical inventions from the JSON (different from the correct invention) - List allInventions = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String invention = result.path("inventionLabel").path("value").asText(); - if (!invention.equals(correctInvention)) { - allInventions.add(invention); - } - } - return allInventions; - } - - private List selectRandomIncorrectInventions(List allInventions, String correctInvention, int count) { - List incorrectInventions = new ArrayList<>(); - while (incorrectInventions.size() < count && allInventions.size() > 0) { - int randomIndex = random.nextInt(allInventions.size()); - String selectedInvention = allInventions.remove(randomIndex); - if (!selectedInvention.equals(correctInvention) && !incorrectInventions.contains(selectedInvention)) { - incorrectInventions.add(selectedInvention); - } - } - return incorrectInventions; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String inventionLabel = result.path("inventionLabel").path("value").asText(); - return selectRandomIncorrectInventions(getAllInventions(results, inventionLabel), inventionLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("inventionLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?invention ?inventionLabel ?historicalEvent ?historicalEventLabel\n" + - "WHERE {" + - " ?invention wdt:P31 wd:Q39614 ." + - " ?historicalEvent wdt:P31 wd:Q198 ." + - " OPTIONAL { ?invention wdt:P921 ?historicalEvent } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?inventionLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java deleted file mode 100644 index 17cce194..00000000 --- a/src/main/java/com/uniovi/components/generators/history/HistoricalLeaderQuestionGeneration.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class HistoricalLeaderQuestionGeneration extends AbstractHistoryGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which historical leader is associated with "); - put("es", "¿Con qué líder histórico se asocia "); - put("fr", "Quel leader historique est associé à "); - } - }; - - public HistoricalLeaderQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllLeaders(JsonNode resultsNode, String correctLeader) { - // Obtaining all historical leaders from the JSON (different from the correct leader) - List allLeaders = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String leader = result.path("leaderLabel").path("value").asText(); - if (!leader.equals(correctLeader)) { - allLeaders.add(leader); - } - } - return allLeaders; - } - - private List selectRandomIncorrectLeaders(List allLeaders, String correctLeader, int count) { - List incorrectLeaders = new ArrayList<>(); - while (incorrectLeaders.size() < count && allLeaders.size() > 0) { - int randomIndex = random.nextInt(allLeaders.size()); - String selectedLeader = allLeaders.remove(randomIndex); - if (!selectedLeader.equals(correctLeader) && !incorrectLeaders.contains(selectedLeader)) { - incorrectLeaders.add(selectedLeader); - } - } - return incorrectLeaders; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String leaderLabel = result.path("leaderLabel").path("value").asText(); - return selectRandomIncorrectLeaders(getAllLeaders(results, leaderLabel), leaderLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("leaderLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?leader ?leaderLabel ?historicalEvent ?historicalEventLabel\n" + - "WHERE {" + - " ?leader wdt:P31 wd:Q5 ." + - " ?historicalEvent wdt:P31 wd:Q198 ." + - " OPTIONAL { ?leader wdt:P6 ?historicalEvent } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?leaderLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java b/src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java deleted file mode 100644 index b1a7f81c..00000000 --- a/src/main/java/com/uniovi/components/generators/history/HistoricalPeriodQuestionGeneration.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.history; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.*; - -public class HistoricalPeriodQuestionGeneration extends AbstractHistoryGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which historical period is associated with "); - put("es", "¿Con qué período histórico se asocia "); - put("fr", "Quelle période historique est associée à "); - } - }; - - public HistoricalPeriodQuestionGeneration(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - private List getAllPeriods(JsonNode resultsNode, String correctPeriod) { - // Obtaining all historical periods from the JSON (different from the correct period) - List allPeriods = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String period = result.path("periodLabel").path("value").asText(); - if (!period.equals(correctPeriod)) { - allPeriods.add(period); - } - } - return allPeriods; - } - - private List selectRandomIncorrectPeriods(List allPeriods, String correctPeriod, int count) { - List incorrectPeriods = new ArrayList<>(); - while (incorrectPeriods.size() < count && allPeriods.size() > 0) { - int randomIndex = random.nextInt(allPeriods.size()); - String selectedPeriod = allPeriods.remove(randomIndex); - if (!selectedPeriod.equals(correctPeriod) && !incorrectPeriods.contains(selectedPeriod)) { - incorrectPeriods.add(selectedPeriod); - } - } - return incorrectPeriods; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String periodLabel = result.path("periodLabel").path("value").asText(); - return selectRandomIncorrectPeriods(getAllPeriods(results, periodLabel), periodLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("periodLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("historicalEventLabel").path("value").asText() + "?"; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?period ?periodLabel ?historicalEvent ?historicalEventLabel\n" + - "WHERE {" + - " ?period wdt:P31 wd:Q186067 ." + - " ?historicalEvent wdt:P31 wd:Q198 ." + - " OPTIONAL { ?period wdt:P155 ?historicalEvent } ." + - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}" + - "ORDER BY ?periodLabel"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java b/src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java deleted file mode 100644 index 89eb2bef..00000000 --- a/src/main/java/com/uniovi/components/generators/movie/AbstractMovieGenerator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.uniovi.components.generators.movie; - -import com.uniovi.components.generators.AbstractQuestionGenerator; -import com.uniovi.entities.Category; -import com.uniovi.services.CategoryService; - -public abstract class AbstractMovieGenerator extends AbstractQuestionGenerator { - - protected AbstractMovieGenerator(CategoryService categoryService) { - super(categoryService); - } - - @Override - public Category getCategory() { - return categoryService.getCategoryByName("Movie"); - } -} diff --git a/src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java deleted file mode 100644 index 35cd2ab2..00000000 --- a/src/main/java/com/uniovi/components/generators/movie/MovieDirectorQuestionGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.movie; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class MovieDirectorQuestionGenerator extends AbstractMovieGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Who directed the movie "); - put("es", "¿Quién dirigió la película "); - put("fr", "Qui a dirigé le film "); - } - }; - - public MovieDirectorQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?director ?directorLabel ?movie ?movieLabel\n" + - "WHERE {" + - " ?director wdt:P31 wd:Q5 ." + // Instance of Human - " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film - " ?movie wdt:P57 ?director ." + // Director - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllMovies(JsonNode resultsNode, String correctMovie) { - List allMovies = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String movie = result.path("movieLabel").path("value").asText(); - if (!movie.equals(correctMovie)) { - allMovies.add(movie); - } - } - return allMovies; - } - - private List selectRandomIncorrectMovies(List allMovies, String correctMovie, int count) { - List incorrectMovies = new ArrayList<>(); - while (incorrectMovies.size() < count && allMovies.size() > 0) { - int randomIndex = random.nextInt(allMovies.size()); - String selectedMovie = allMovies.remove(randomIndex); - if (!selectedMovie.equals(correctMovie) && !incorrectMovies.contains(selectedMovie)) { - incorrectMovies.add(selectedMovie); - } - } - return incorrectMovies; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String movieLabel = result.path("movieLabel").path("value").asText(); - return selectRandomIncorrectMovies(getAllMovies(results, movieLabel), movieLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("directorLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("movieLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java deleted file mode 100644 index 8da6a045..00000000 --- a/src/main/java/com/uniovi/components/generators/movie/MovieGenreQuestionGenerator.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.uniovi.components.generators.movie; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class MovieGenreQuestionGenerator extends AbstractMovieGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Which genre does the movie "); - put("es", "¿A qué género pertenece la película "); - put("fr", "À quel genre appartient le film "); - } - }; - - public MovieGenreQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?movie ?movieLabel ?genre ?genreLabel\n" + - "WHERE {" + - " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film - " ?movie wdt:P136 ?genre ." + // Genre - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllMovies(JsonNode resultsNode, String correctMovie) { - List allMovies = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String movie = result.path("movieLabel").path("value").asText(); - if (!movie.equals(correctMovie)) { - allMovies.add(movie); - } - } - return allMovies; - } - - private List selectRandomIncorrectGenres(List allMovies, String correctMovie, int count) { - List incorrectGenres = new ArrayList<>(); - while (incorrectGenres.size() < count && allMovies.size() > 0) { - int randomIndex = random.nextInt(allMovies.size()); - String selectedMovie = allMovies.remove(randomIndex); - if (!selectedMovie.equals(correctMovie) && !incorrectGenres.contains(selectedMovie)) { - incorrectGenres.add(selectedMovie); - } - } - return incorrectGenres; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String movieLabel = result.path("movieLabel").path("value").asText(); - return selectRandomIncorrectGenres(getAllMovies(results, movieLabel), movieLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("genreLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("movieLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java deleted file mode 100644 index 88b78d5d..00000000 --- a/src/main/java/com/uniovi/components/generators/movie/MovieReleaseYearQuestionGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.movie; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class MovieReleaseYearQuestionGenerator extends AbstractMovieGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "In which year was the movie "); - put("es", "¿En qué año se lanzó la película "); - put("fr", "En quelle année est sorti le film "); - } - }; - - public MovieReleaseYearQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?movie ?movieLabel ?releaseYear\n" + - "WHERE {" + - " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film - " ?movie wdt:P577 ?releaseDate ." + // Release date - " BIND(YEAR(?releaseDate) AS ?releaseYear)" + // Extract year - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllMovies(JsonNode resultsNode, String correctMovie) { - List allMovies = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String movie = result.path("movieLabel").path("value").asText(); - if (!movie.equals(correctMovie)) { - allMovies.add(movie); - } - } - return allMovies; - } - - private List selectRandomIncorrectYears(List allMovies, String correctMovie, int count) { - List incorrectYears = new ArrayList<>(); - while (incorrectYears.size() < count && allMovies.size() > 0) { - int randomIndex = random.nextInt(allMovies.size()); - String selectedMovie = allMovies.remove(randomIndex); - if (!selectedMovie.equals(correctMovie) && !incorrectYears.contains(selectedMovie)) { - incorrectYears.add(selectedMovie); - } - } - return incorrectYears; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String movieLabel = result.path("movieLabel").path("value").asText(); - return selectRandomIncorrectYears(getAllMovies(results, movieLabel), movieLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("releaseYear").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("movieLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java deleted file mode 100644 index 84f61091..00000000 --- a/src/main/java/com/uniovi/components/generators/movie/OriginalTitleQuestionGenerator.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.uniovi.components.generators.movie; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class OriginalTitleQuestionGenerator extends AbstractMovieGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What is the original title of the movie "); - put("es", "¿Cuál es el título original de la película "); - put("fr", "Quel est le titre original du film "); - } - }; - - public OriginalTitleQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?movie ?movieLabel ?originalTitle\n" + - "WHERE {" + - " ?movie wdt:P31 wd:Q11424 ." + // Instance of Film - " ?movie wdt:P1476 ?originalTitle ." + // Original title - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllMovies(JsonNode resultsNode, String correctMovie) { - List allMovies = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String movie = result.path("movieLabel").path("value").asText(); - if (!movie.equals(correctMovie)) { - allMovies.add(movie); - } - } - return allMovies; - } - - private List selectRandomIncorrectTitles(List allMovies, String correctMovie, int count) { - List incorrectTitles = new ArrayList<>(); - while (incorrectTitles.size() < count && allMovies.size() > 0) { - int randomIndex = random.nextInt(allMovies.size()); - String selectedMovie = allMovies.remove(randomIndex); - if (!selectedMovie.equals(correctMovie) && !incorrectTitles.contains(selectedMovie)) { - incorrectTitles.add(selectedMovie); - } - } - return incorrectTitles; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String movieLabel = result.path("movieLabel").path("value").asText(); - return selectRandomIncorrectTitles(getAllMovies(results, movieLabel), movieLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("originalTitle").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("movieLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java b/src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java deleted file mode 100644 index 8978f068..00000000 --- a/src/main/java/com/uniovi/components/generators/science/AbstractScienceGenerator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.uniovi.components.generators.science; - -import com.uniovi.components.generators.AbstractQuestionGenerator; -import com.uniovi.entities.Category; -import com.uniovi.services.CategoryService; - -public abstract class AbstractScienceGenerator extends AbstractQuestionGenerator { - - protected AbstractScienceGenerator(CategoryService categoryService) { - super(categoryService); - } - - @Override - public Category getCategory() { - return categoryService.getCategoryByName("Science"); - } -} diff --git a/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java deleted file mode 100644 index 4c907fba..00000000 --- a/src/main/java/com/uniovi/components/generators/science/MathPhysicsFormulaQuestionGenerator.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.uniovi.components.generators.science; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class MathPhysicsFormulaQuestionGenerator extends AbstractScienceGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What is the formula for "); - put("es", "¿Cuál es la fórmula para "); - put("fr", "Quelle est la formule pour "); - } - }; - - public MathPhysicsFormulaQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?formula ?formulaLabel\n" + - "WHERE {" + - " ?formula wdt:P31 wd:Q5185279 ." + // Instance of Mathematical or physical formula - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllFormulas(JsonNode resultsNode, String correctFormula) { - List allFormulas = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String formula = result.path("formulaLabel").path("value").asText(); - if (!formula.equals(correctFormula)) { - allFormulas.add(formula); - } - } - return allFormulas; - } - - private List selectRandomIncorrectFormulas(List allFormulas, String correctFormula, int count) { - List incorrectFormulas = new ArrayList<>(); - while (incorrectFormulas.size() < count && allFormulas.size() > 0) { - int randomIndex = random.nextInt(allFormulas.size()); - String selectedFormula = allFormulas.remove(randomIndex); - if (!selectedFormula.equals(correctFormula) && !incorrectFormulas.contains(selectedFormula)) { - incorrectFormulas.add(selectedFormula); - } - } - return incorrectFormulas; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String formulaLabel = result.path("formulaLabel").path("value").asText(); - return selectRandomIncorrectFormulas(getAllFormulas(results, formulaLabel), formulaLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("formulaLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("formulaLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java deleted file mode 100644 index 36304b41..00000000 --- a/src/main/java/com/uniovi/components/generators/science/ScientificAchievementQuestionGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.science; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ScientificAchievementQuestionGenerator extends AbstractScienceGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "What significant achievement is associated with "); - put("es", "¿Qué logro significativo está asociado con "); - put("fr", "Quelle réalisation significative est associée à "); - } - }; - - public ScientificAchievementQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?scientist ?scientistLabel ?achievement ?achievementLabel\n" + - "WHERE {" + - " ?scientist wdt:P31 wd:Q5 ." + // Instance of Human - " ?scientist wdt:P166 ?achievement ." + // Notable achievement - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllAchievements(JsonNode resultsNode, String correctAchievement) { - List allAchievements = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String achievement = result.path("achievementLabel").path("value").asText(); - if (!achievement.equals(correctAchievement)) { - allAchievements.add(achievement); - } - } - return allAchievements; - } - - private List selectRandomIncorrectAchievements(List allAchievements, String correctAchievement, int count) { - List incorrectAchievements = new ArrayList<>(); - while (incorrectAchievements.size() < count && allAchievements.size() > 0) { - int randomIndex = random.nextInt(allAchievements.size()); - String selectedAchievement = allAchievements.remove(randomIndex); - if (!selectedAchievement.equals(correctAchievement) && !incorrectAchievements.contains(selectedAchievement)) { - incorrectAchievements.add(selectedAchievement); - } - } - return incorrectAchievements; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String achievementLabel = result.path("achievementLabel").path("value").asText(); - return selectRandomIncorrectAchievements(getAllAchievements(results, achievementLabel), achievementLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("achievementLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("scientistLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java deleted file mode 100644 index b868667b..00000000 --- a/src/main/java/com/uniovi/components/generators/science/ScientificDiscoveryQuestionGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.science; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ScientificDiscoveryQuestionGenerator extends AbstractScienceGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Who discovered "); - put("es", "¿Quién descubrió "); - put("fr", "Qui a découvert "); - } - }; - - public ScientificDiscoveryQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?scientist ?scientistLabel ?discovery ?discoveryLabel\n" + - "WHERE {" + - " ?scientist wdt:P31 wd:Q5 ." + // Instance of Human - " ?scientist wdt:P61 ?discovery ." + // Discovery - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllDiscoveries(JsonNode resultsNode, String correctDiscovery) { - List allDiscoveries = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String discovery = result.path("discoveryLabel").path("value").asText(); - if (!discovery.equals(correctDiscovery)) { - allDiscoveries.add(discovery); - } - } - return allDiscoveries; - } - - private List selectRandomIncorrectDiscoveries(List allDiscoveries, String correctDiscovery, int count) { - List incorrectDiscoveries = new ArrayList<>(); - while (incorrectDiscoveries.size() < count && allDiscoveries.size() > 0) { - int randomIndex = random.nextInt(allDiscoveries.size()); - String selectedDiscovery = allDiscoveries.remove(randomIndex); - if (!selectedDiscovery.equals(correctDiscovery) && !incorrectDiscoveries.contains(selectedDiscovery)) { - incorrectDiscoveries.add(selectedDiscovery); - } - } - return incorrectDiscoveries; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String discoveryLabel = result.path("discoveryLabel").path("value").asText(); - return selectRandomIncorrectDiscoveries(getAllDiscoveries(results, discoveryLabel), discoveryLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("scientistLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("discoveryLabel").path("value").asText() + "?"; - } -} diff --git a/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java b/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java deleted file mode 100644 index 55763766..00000000 --- a/src/main/java/com/uniovi/components/generators/science/ScientistBirthplaceQuestionGenerator.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.uniovi.components.generators.science; - -import com.fasterxml.jackson.databind.JsonNode; -import com.uniovi.services.CategoryService; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ScientistBirthplaceQuestionGenerator extends AbstractScienceGenerator { - private static final Map STATEMENTS = new HashMap<>() { - { - put("en", "Where was the scientist "); - put("es", "¿Dónde nació el científico "); - put("fr", "Où est né le scientifique "); - } - }; - - public ScientistBirthplaceQuestionGenerator(CategoryService categoryService, String language) { - super(categoryService); - this.statement = STATEMENTS.get(language); - this.language = language; - } - - @Override - public String getQuery() { - return "SELECT DISTINCT ?scientist ?scientistLabel ?birthplace ?birthplaceLabel\n" + - "WHERE {" + - " ?scientist wdt:P31 wd:Q5 ." + // Instance of Human - " ?scientist wdt:P19 ?birthplace ." + // Place of birth - " SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE]," + language + "\" }" + - "}"; - } - - private List getAllBirthplaces(JsonNode resultsNode, String correctBirthplace) { - List allBirthplaces = new ArrayList<>(); - for (JsonNode result : resultsNode) { - String birthplace = result.path("birthplaceLabel").path("value").asText(); - if (!birthplace.equals(correctBirthplace)) { - allBirthplaces.add(birthplace); - } - } - return allBirthplaces; - } - - private List selectRandomIncorrectBirthplaces(List allBirthplaces, String correctBirthplace, int count) { - List incorrectBirthplaces = new ArrayList<>(); - while (incorrectBirthplaces.size() < count && allBirthplaces.size() > 0) { - int randomIndex = random.nextInt(allBirthplaces.size()); - String selectedBirthplace = allBirthplaces.remove(randomIndex); - if (!selectedBirthplace.equals(correctBirthplace) && !incorrectBirthplaces.contains(selectedBirthplace)) { - incorrectBirthplaces.add(selectedBirthplace); - } - } - return incorrectBirthplaces; - } - - @Override - protected List generateOptions(JsonNode results, JsonNode result) { - String birthplaceLabel = result.path("birthplaceLabel").path("value").asText(); - return selectRandomIncorrectBirthplaces(getAllBirthplaces(results, birthplaceLabel), birthplaceLabel, 3); - } - - @Override - protected String generateCorrectAnswer(JsonNode result) { - return result.path("birthplaceLabel").path("value").asText(); - } - - @Override - protected String getQuestionSubject(JsonNode result) { - return this.statement + result.path("scientistLabel").path("value").asText() + "?"; - } -} From 4ac734a9f3aa8680f8ab92bcc0866fa5b1066009 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 04:35:17 +0200 Subject: [PATCH 33/59] Test controller and temporary comments on some classes that used the old question generation system --- .../components/MultipleQuestionGenerator.java | 3 +- .../generators/QuestionGeneratorV2.java | 21 ++- .../services/InsertSampleDataService.java | 167 +++++++++--------- 3 files changed, 91 insertions(+), 100 deletions(-) diff --git a/src/main/java/com/uniovi/components/MultipleQuestionGenerator.java b/src/main/java/com/uniovi/components/MultipleQuestionGenerator.java index d8409cc5..7a10c2ed 100644 --- a/src/main/java/com/uniovi/components/MultipleQuestionGenerator.java +++ b/src/main/java/com/uniovi/components/MultipleQuestionGenerator.java @@ -4,6 +4,7 @@ import com.uniovi.entities.Category; import com.uniovi.entities.Question; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -14,7 +15,7 @@ public MultipleQuestionGenerator(QuestionGenerator... generators) { this.generators = generators; } - public List getQuestions() { + public List getQuestions() throws IOException { List questions = new ArrayList<>(); for (QuestionGenerator generator : generators) { questions.addAll(generator.getQuestions()); diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index 8b7d39c8..1a440e9e 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -6,6 +6,7 @@ import com.uniovi.entities.Category; import com.uniovi.entities.Question; +import java.io.IOException; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; @@ -37,7 +38,7 @@ public String getQuery() { } @Override - public List getQuestions() { + public List getQuestions() throws IOException { List questions = new ArrayList<>(); JsonNode categories = jsonNode.findValue("categories"); for(JsonNode category : categories){ @@ -51,7 +52,7 @@ public List getQuestions() { return questions; } - private List generateQuestion(JsonNode question, Category cat) { + private List generateQuestion(JsonNode question, Category cat) throws IOException { // Get the SPARQL query from the JSON String query = question.get("sparqlQuery").textValue(); @@ -73,15 +74,15 @@ private List generateQuestion(JsonNode question, Category cat) { for (JsonNode result : results) { // Generate the correct answer - String correctAnswer = result.get(answerLabel).textValue(); + String correctAnswer = result.path(answerLabel).path("value").asText(); Answer correct = new Answer(correctAnswer, true); // Generate the options List options = this.generateOptions(results, correctAnswer, answerLabel); - + options.add(correct); // Generate the question statement - String questionStatement = statement.replace(question_placeholder, result.get(questionLabel).textValue()); + String questionStatement = statement.replace(question_placeholder, result.path(questionLabel).path("value").asText()); // Generate the question questions.add(new Question(questionStatement, options, correct, cat, language)); @@ -92,7 +93,7 @@ private List generateQuestion(JsonNode question, Category cat) { private List generateOptions(JsonNode results, String correctAnswer, String answerLabel) { List options = new ArrayList<>(); for (JsonNode result : results) { - String option = result.get(answerLabel).textValue(); + String option = result.path(answerLabel).path("value").asText(); if (!option.equals(correctAnswer)) { options.add(new Answer(option, false)); } @@ -115,14 +116,15 @@ private String prepareStatement(JsonNode question) { return null; } - private JsonNode getQueryResult(String query) { + private JsonNode getQueryResult(String query) throws IOException { + System.out.println("Query: " + query); HttpClient client = HttpClient.newHttpClient(); JsonNode resultsNode; try { String endpointUrl = "https://query.wikidata.org/sparql?query=" + - URLEncoder.encode(this.getQuery(), StandardCharsets.UTF_8) + + URLEncoder.encode(query, StandardCharsets.UTF_8) + "&format=json"; HttpRequest request = HttpRequest.newBuilder() @@ -141,10 +143,7 @@ private JsonNode getQueryResult(String query) { } catch (InterruptedException e) { throw new QuestionGeneratorException("Generation of questions was interrupted"); - } catch (Exception e) { - throw new QuestionGeneratorException("An error occurred while generating questions"); } - return resultsNode; } diff --git a/src/main/java/com/uniovi/services/InsertSampleDataService.java b/src/main/java/com/uniovi/services/InsertSampleDataService.java index ff76371a..cc158cd8 100644 --- a/src/main/java/com/uniovi/services/InsertSampleDataService.java +++ b/src/main/java/com/uniovi/services/InsertSampleDataService.java @@ -1,108 +1,99 @@ package com.uniovi.services; import com.uniovi.components.MultipleQuestionGenerator; -import com.uniovi.components.generators.QuestionGenerator; -import com.uniovi.components.generators.geography.BorderQuestionGenerator; -import com.uniovi.components.generators.geography.CapitalQuestionGenerator; -import com.uniovi.components.generators.geography.ContinentQuestionGeneration; import com.uniovi.dto.PlayerDto; -import com.uniovi.entities.Associations; -import com.uniovi.entities.GameSession; -import com.uniovi.entities.Player; import com.uniovi.entities.Question; import com.uniovi.repositories.GameSessionRepository; import com.uniovi.repositories.QuestionRepository; -import jakarta.annotation.PostConstruct; import jakarta.transaction.Transactional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.core.env.Environment; import org.springframework.stereotype.Service; import java.io.IOException; -import java.time.LocalDateTime; -import java.util.*; +import java.util.Arrays; +import java.util.List; @Service public class InsertSampleDataService { - private final PlayerService playerService; - private final QuestionService questionService; - private final CategoryService categoryService; - private final QuestionRepository questionRepository; - private final GameSessionRepository gameSessionRepository; - private Environment environment; - - private Logger log = LoggerFactory.getLogger(InsertSampleDataService.class); - - public InsertSampleDataService(PlayerService playerService, QuestionService questionService, - CategoryService categoryService, QuestionRepository questionRepository, - GameSessionRepository gameSessionRepository, Environment environment) { - this.playerService = playerService; - this.questionService = questionService; - this.categoryService = categoryService; - this.questionRepository = questionRepository; - this.gameSessionRepository = gameSessionRepository; - this.environment = environment; - } - - @Transactional - @EventListener(ApplicationReadyEvent.class) // Uncomment this line to insert sample data on startup - public void insertSampleQuestions() throws InterruptedException, IOException { - if (!playerService.getUserByEmail("test@test.com").isPresent()) { - PlayerDto player = new PlayerDto(); - player.setEmail("test@test.com"); - player.setUsername("test"); - player.setPassword("test"); - player.setRoles(new String[]{"ROLE_USER"}); - playerService.generateApiKey(playerService.addNewPlayer(player)); - } - - if (Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("test")))) { - log.info("Test profile active, skipping sample data insertion"); - return; - } - - generateSampleData(); - } - - @Transactional - public void generateTestQuestions() { - questionRepository.deleteAll(); - questionService.testQuestions(4); - } - - @Transactional - public void generateSampleData() throws InterruptedException, IOException { - - questionRepository.deleteAll(); - - MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( - new ContinentQuestionGeneration(categoryService, Question.ENGLISH), - new CapitalQuestionGenerator(categoryService, Question.ENGLISH), - new BorderQuestionGenerator(categoryService, Question.ENGLISH) - ); - List questionsEn = allQuestionGenerator.getQuestions(); - questionsEn.forEach(questionService::addNewQuestion); - - allQuestionGenerator = new MultipleQuestionGenerator( - new ContinentQuestionGeneration(categoryService, Question.SPANISH), - new CapitalQuestionGenerator(categoryService, Question.SPANISH), - new BorderQuestionGenerator(categoryService, Question.SPANISH) - ); - List questionsEs = allQuestionGenerator.getQuestions(); - questionsEs.forEach(questionService::addNewQuestion); - - allQuestionGenerator = new MultipleQuestionGenerator( - new ContinentQuestionGeneration(categoryService, Question.FRENCH), - new CapitalQuestionGenerator(categoryService, Question.FRENCH), - new BorderQuestionGenerator(categoryService, Question.FRENCH) - ); - List questionsFr = allQuestionGenerator.getQuestions(); - questionsFr.forEach(questionService::addNewQuestion); - - log.info("Sample questions inserted"); - } +// private final PlayerService playerService; +// private final QuestionService questionService; +// private final CategoryService categoryService; +// private final QuestionRepository questionRepository; +// private final GameSessionRepository gameSessionRepository; +// private Environment environment; +// +// private Logger log = LoggerFactory.getLogger(InsertSampleDataService.class); +// +//// public InsertSampleDataService(PlayerService playerService, QuestionService questionService, +//// CategoryService categoryService, QuestionRepository questionRepository, +//// GameSessionRepository gameSessionRepository, Environment environment) { +//// this.playerService = playerService; +//// this.questionService = questionService; +//// this.categoryService = categoryService; +//// this.questionRepository = questionRepository; +//// this.gameSessionRepository = gameSessionRepository; +//// this.environment = environment; +//// } +//// +//// @Transactional +//// @EventListener(ApplicationReadyEvent.class) // Uncomment this line to insert sample data on startup +//// public void insertSampleQuestions() throws InterruptedException, IOException { +//// if (!playerService.getUserByEmail("test@test.com").isPresent()) { +//// PlayerDto player = new PlayerDto(); +//// player.setEmail("test@test.com"); +//// player.setUsername("test"); +//// player.setPassword("test"); +//// player.setRoles(new String[]{"ROLE_USER"}); +//// playerService.generateApiKey(playerService.addNewPlayer(player)); +//// } +//// +//// if (Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("test")))) { +//// log.info("Test profile active, skipping sample data insertion"); +//// return; +//// } +//// +//// generateSampleData(); +//// } +//// +//// @Transactional +//// public void generateTestQuestions() { +//// questionRepository.deleteAll(); +//// questionService.testQuestions(4); +//// } +//// +//// @Transactional +//// public void generateSampleData() throws InterruptedException, IOException { +//// +//// questionRepository.deleteAll(); +//// +//// MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( +//// new ContinentQuestionGeneration(categoryService, Question.ENGLISH), +//// new CapitalQuestionGenerator(categoryService, Question.ENGLISH), +//// new BorderQuestionGenerator(categoryService, Question.ENGLISH) +//// ); +//// List questionsEn = allQuestionGenerator.getQuestions(); +//// questionsEn.forEach(questionService::addNewQuestion); +//// +//// allQuestionGenerator = new MultipleQuestionGenerator( +//// new ContinentQuestionGeneration(categoryService, Question.SPANISH), +//// new CapitalQuestionGenerator(categoryService, Question.SPANISH), +//// new BorderQuestionGenerator(categoryService, Question.SPANISH) +//// ); +//// List questionsEs = allQuestionGenerator.getQuestions(); +//// questionsEs.forEach(questionService::addNewQuestion); +//// +//// allQuestionGenerator = new MultipleQuestionGenerator( +//// new ContinentQuestionGeneration(categoryService, Question.FRENCH), +//// new CapitalQuestionGenerator(categoryService, Question.FRENCH), +//// new BorderQuestionGenerator(categoryService, Question.FRENCH) +//// ); +//// List questionsFr = allQuestionGenerator.getQuestions(); +//// questionsFr.forEach(questionService::addNewQuestion); +//// +//// log.info("Sample questions inserted"); +//// } } \ No newline at end of file From bd06490ff643d3dc02eea8843d95fa56c2a7df5e Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 04:53:51 +0200 Subject: [PATCH 34/59] New question generator tested and working --- .../QuestionGeneratorTestController.java | 24 +++++++++++++++---- .../generators/QuestionGenerator.java | 3 ++- .../generators/QuestionGeneratorV2.java | 21 ++++++++++++---- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java b/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java index bb954701..7154ba5f 100644 --- a/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java +++ b/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java @@ -1,21 +1,35 @@ package com.uniovi.components; -import com.uniovi.components.generators.geography.CapitalQuestionGenerator; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.uniovi.components.generators.QuestionGeneratorV2; import com.uniovi.entities.Question; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.io.File; +import java.io.IOException; import java.util.List; @RestController public class QuestionGeneratorTestController { - /*@RequestMapping("/test") - public void test() { + private final String jsonFilePath = "src/main/resources/static/JSON/QuestionTemplates.json"; + + @RequestMapping("/test") + public void test() throws IOException { + // Crear un objeto File con la ruta del archivo JSON + File jsonFile = new File(jsonFilePath); + + // Crear un ObjectMapper de Jackson + ObjectMapper objectMapper = new ObjectMapper(); + + // Leer el archivo JSON y convertirlo en un JsonNode + JsonNode jsonNode = objectMapper.readTree(jsonFile); + QuestionGeneratorV2 qgen = new QuestionGeneratorV2(jsonNode, Question.SPANISH); List q = qgen.getQuestions(); for(Question question : q){ System.out.println(question); } - }*/ + } } diff --git a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java index 7b552684..549cefe8 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java @@ -4,11 +4,12 @@ import com.uniovi.entities.Question; import org.springframework.stereotype.Component; +import java.io.IOException; import java.util.List; @Component public interface QuestionGenerator { String getQuery(); - List getQuestions(); + List getQuestions() throws IOException; } diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index 1a440e9e..49268be0 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -85,18 +85,31 @@ private List generateQuestion(JsonNode question, Category cat) throws String questionStatement = statement.replace(question_placeholder, result.path(questionLabel).path("value").asText()); // Generate the question - questions.add(new Question(questionStatement, options, correct, cat, language)); + Question q = new Question(questionStatement, options, correct, cat, language); + + // Scramble the options + q.scrambleOptions(); + + // Add the question to the list + questions.add(q); } return questions; } private List generateOptions(JsonNode results, String correctAnswer, String answerLabel) { List options = new ArrayList<>(); - for (JsonNode result : results) { - String option = result.path(answerLabel).path("value").asText(); - if (!option.equals(correctAnswer)) { + List usedOptions = new ArrayList<>(); + int size = results.size(); + int tries = 0; + + while (options.size() < 3 && tries < 10){ + int random = (int) (Math.random() * size); + String option = results.get(random).path(answerLabel).path("value").asText(); + if (!option.equals(correctAnswer) && !usedOptions.contains(option) ) { + usedOptions.add(option); options.add(new Answer(option, false)); } + tries++; } return options; } From 3f4c7031428f954af2a7d5cce02d156457303a7b Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 16:02:37 +0200 Subject: [PATCH 35/59] Removed unused method from the question generator interface --- .../com/uniovi/components/generators/QuestionGenerator.java | 2 -- .../uniovi/components/generators/QuestionGeneratorV2.java | 5 ----- 2 files changed, 7 deletions(-) diff --git a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java index 549cefe8..03a92c3f 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java @@ -9,7 +9,5 @@ @Component public interface QuestionGenerator { - - String getQuery(); List getQuestions() throws IOException; } diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index 49268be0..20d2a34f 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -32,11 +32,6 @@ public QuestionGeneratorV2(JsonNode jsonNode, String language) { this.language = language; } - @Override - public String getQuery() { - return null; - } - @Override public List getQuestions() throws IOException { List questions = new ArrayList<>(); From d0c2200161f8003fa489c68be74182dbeed256cd Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 16:40:57 +0200 Subject: [PATCH 36/59] Added new question and improved the queries --- .../static/JSON/QuestionTemplates.json | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/main/resources/static/JSON/QuestionTemplates.json b/src/main/resources/static/JSON/QuestionTemplates.json index 29df09ae..708d0ed8 100644 --- a/src/main/resources/static/JSON/QuestionTemplates.json +++ b/src/main/resources/static/JSON/QuestionTemplates.json @@ -24,7 +24,7 @@ ], "question": "countryLabel", "answer": "capitalLabel", - "sparqlQuery": "select distinct ?country ?[QUESTION] ?capital ?[ANSWER] where {\n ?country wdt:P31 wd:Q6256 .\n ?capital wdt:P31 wd:Q5119 .\n ?country wdt:P36 ?capital .\n ?country rdfs:label ?countryLabel .\n ?capital rdfs:label ?capitalLabel .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?capitalLabel)=\"[LANGUAGE]\")\n }" + "sparqlQuery": "select distinct ?country ?[QUESTION] ?capital ?[ANSWER] where {\n ?country wdt:P31 wd:Q6256 .\n ?capital wdt:P31 wd:Q5119 .\n ?country wdt:P36 ?capital .\n ?country rdfs:label ?[QUESTION] .\n ?capital rdfs:label ?[ANSWER] .\n FILTER(LANG(?[QUESTION])=\"[LANGUAGE]\" && LANG(?[ANSWER])=\"[LANGUAGE]\")\n }" }, { "type": "currency", @@ -44,7 +44,32 @@ ], "question": "countryLabel", "answer": "currencyLabel", - "sparqlQuery": "select distinct ?country ?[QUESTION] ?currency ?[ANSWER] where {\n ?country wdt:P31 wd:Q6256 .\n ?currency wdt:P31 wd:Q8142 .\n ?country wdt:P38 ?currency .\n ?country rdfs:label ?countryLabel .\n ?currency rdfs:label ?currencyLabel .\n FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240} .\n FILTER(LANG(?countryLabel)=\"[LANGUAGE]\" && LANG(?currencyLabel)=\"[LANGUAGE]\")\n }" + "sparqlQuery": "select distinct ?country ?[QUESTION] ?currency ?[ANSWER] where {\n ?country wdt:P31 wd:Q6256 .\n ?currency wdt:P31 wd:Q8142 .\n ?country wdt:P38 ?currency .\n ?country rdfs:label ?[QUESTION] .\n ?currency rdfs:label ?[ANSWER] .\n FILTER NOT EXISTS {?country wdt:P31 wd:Q3024240} .\n FILTER(LANG(?[QUESTION])=\"[LANGUAGE]\" && LANG(?[ANSWER])=\"[LANGUAGE]\")\n }" + } + ] + }, + { + "name": "Science", + "questions": [ + { + "type": "element", + "statements": [ + { + "language": "es", + "statement": "¿Cuál es el símbolo químico del [QUESTION]?" + }, + { + "language": "en", + "statement": "What is the chemical symbol of [QUESTION]?" + }, + { + "language": "fr", + "statement": "Quel est le symbole chimique du [QUESTION]?" + } + ], + "question": "elementLabel", + "answer": "symbol", + "sparqlQuery": "select distinct ?element ?[QUESTION] ?[ANSWER] where {\n ?element wdt:P31 wd:Q11344 .\n ?element wdt:P246 ?[ANSWER] .\n ?element rdfs:label ?[QUESTION] .\n FILTER NOT EXISTS {?element wdt:P31 wd:Q1299291} .\n FILTER(LANG(?[QUESTION])=\"[LANGUAGE]\")\n }" } ] } From 51f41d8ddfe8474394e08f67f50a2bff64cb4ac1 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 16:54:58 +0200 Subject: [PATCH 37/59] Added the fourth question --- .../static/JSON/QuestionTemplates.json | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/resources/static/JSON/QuestionTemplates.json b/src/main/resources/static/JSON/QuestionTemplates.json index 708d0ed8..c6323b0d 100644 --- a/src/main/resources/static/JSON/QuestionTemplates.json +++ b/src/main/resources/static/JSON/QuestionTemplates.json @@ -70,6 +70,26 @@ "question": "elementLabel", "answer": "symbol", "sparqlQuery": "select distinct ?element ?[QUESTION] ?[ANSWER] where {\n ?element wdt:P31 wd:Q11344 .\n ?element wdt:P246 ?[ANSWER] .\n ?element rdfs:label ?[QUESTION] .\n FILTER NOT EXISTS {?element wdt:P31 wd:Q1299291} .\n FILTER(LANG(?[QUESTION])=\"[LANGUAGE]\")\n }" + }, + { + "type": "atomic_number", + "statements": [ + { + "language": "es", + "statement": "¿Cuál es el número atómico del [QUESTION]?" + }, + { + "language": "en", + "statement": "What is the atomic number of [QUESTION]?" + }, + { + "language": "fr", + "statement": "Quel est le numéro atomique du [QUESTION]?" + } + ], + "question": "elementLabel", + "answer": "atomicNumber", + "sparqlQuery": "select distinct ?element ?[QUESTION] ?[ANSWER] where {\n ?element wdt:P31 wd:Q11344 .\n ?element wdt:P1086 ?[ANSWER] .\n ?element rdfs:label ?[QUESTION] .\n FILTER NOT EXISTS {?element wdt:P31 wd:Q1299291} .\n FILTER(LANG(?[QUESTION])=\"es\")\n }" } ] } From 7a27e6e3fd6212369b39ff7ea552a5d1fc33dd4a Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 17:16:03 +0200 Subject: [PATCH 38/59] Started implementation of the QuestionGeneratorService with scheduling for the question generation --- .../java/com/uniovi/WiqEs04bApplication.java | 2 + .../QuestionGeneratorTestController.java | 4 +- .../generators/QuestionGenerator.java | 2 +- .../generators/QuestionGeneratorV2.java | 6 +-- .../services/QuestionGeneratorService.java | 52 +++++++++++++++++++ src/main/resources/application.properties | 5 +- 6 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/uniovi/services/QuestionGeneratorService.java diff --git a/src/main/java/com/uniovi/WiqEs04bApplication.java b/src/main/java/com/uniovi/WiqEs04bApplication.java index 5bfb46bc..fc0a8ac7 100644 --- a/src/main/java/com/uniovi/WiqEs04bApplication.java +++ b/src/main/java/com/uniovi/WiqEs04bApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableScheduling public class WiqEs04bApplication { public static void main(String[] args) { SpringApplication.run(WiqEs04bApplication.class, args); diff --git a/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java b/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java index 7154ba5f..77ee4aa2 100644 --- a/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java +++ b/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java @@ -26,8 +26,8 @@ public void test() throws IOException { // Leer el archivo JSON y convertirlo en un JsonNode JsonNode jsonNode = objectMapper.readTree(jsonFile); - QuestionGeneratorV2 qgen = new QuestionGeneratorV2(jsonNode, Question.SPANISH); - List q = qgen.getQuestions(); + QuestionGeneratorV2 qgen = new QuestionGeneratorV2(jsonNode); + List q = qgen.getQuestions(Question.SPANISH); for(Question question : q){ System.out.println(question); } diff --git a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java index 03a92c3f..6698a041 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java @@ -9,5 +9,5 @@ @Component public interface QuestionGenerator { - List getQuestions() throws IOException; + List getQuestions(String language) throws IOException; } diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index 20d2a34f..fae0323a 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -24,16 +24,16 @@ public class QuestionGeneratorV2 implements QuestionGenerator{ private String answer_placeholder; private String language; - public QuestionGeneratorV2(JsonNode jsonNode, String language) { + public QuestionGeneratorV2(JsonNode jsonNode) { this.jsonNode = jsonNode; this.language_placeholder = jsonNode.get("language_placeholder").textValue(); this.question_placeholder = jsonNode.get("question_placeholder").textValue(); this.answer_placeholder = jsonNode.get("answer_placeholder").textValue(); - this.language = language; } @Override - public List getQuestions() throws IOException { + public List getQuestions(String language) throws IOException { + this.language = language; List questions = new ArrayList<>(); JsonNode categories = jsonNode.findValue("categories"); for(JsonNode category : categories){ diff --git a/src/main/java/com/uniovi/services/QuestionGeneratorService.java b/src/main/java/com/uniovi/services/QuestionGeneratorService.java new file mode 100644 index 00000000..10b44a47 --- /dev/null +++ b/src/main/java/com/uniovi/services/QuestionGeneratorService.java @@ -0,0 +1,52 @@ +package com.uniovi.services; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.uniovi.components.generators.QuestionGeneratorV2; +import com.uniovi.entities.Question; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Stack; + +@Service +public class QuestionGeneratorService { + + private final QuestionService questionService; + + @Value("${question.json.path}") + private String jsonFilePath; + + private Stack types = new Stack<>(); + + public QuestionGeneratorService(QuestionService questionService) { + this.questionService = questionService; + } + + @Scheduled(fixedRate = 150000) + public void generateQuestions() { + + File jsonFile = new File(jsonFilePath); + + ObjectMapper objectMapper = new ObjectMapper(); + + try { + JsonNode jsonNode = objectMapper.readTree(jsonFile); + QuestionGeneratorV2 qgen = new QuestionGeneratorV2(jsonNode); + List qsp = qgen.getQuestions(Question.SPANISH); + qsp.forEach(questionService::addNewQuestion); + List qen = qgen.getQuestions(Question.SPANISH); + qen.forEach(questionService::addNewQuestion); + List qfr = qgen.getQuestions(Question.SPANISH); + qfr.forEach(questionService::addNewQuestion); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ca30d8d3..137847e7 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -12,4 +12,7 @@ spring.jpa.hibernate.ddl-auto=update springdoc.api-docs.path=/api-docs springdoc.swagger-ui.path=/api springdoc.swagger-ui.operationsSorter=method -springdoc.packagesToScan=com.uniovi.controllers.api \ No newline at end of file +springdoc.packagesToScan=com.uniovi.controllers.api + +# Question templates +question.json.path=src/main/resources/static/JSON/QuestionTemplates.json \ No newline at end of file From d829ec906bf629588e23b4b5a8dfecd4805fbb20 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 17:29:03 +0200 Subject: [PATCH 39/59] Added stack to store all the different types of questions along with their category --- .../services/QuestionGeneratorService.java | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/uniovi/services/QuestionGeneratorService.java b/src/main/java/com/uniovi/services/QuestionGeneratorService.java index 10b44a47..70031fe4 100644 --- a/src/main/java/com/uniovi/services/QuestionGeneratorService.java +++ b/src/main/java/com/uniovi/services/QuestionGeneratorService.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.uniovi.components.generators.QuestionGeneratorV2; +import com.uniovi.entities.Category; import com.uniovi.entities.Question; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; @@ -21,10 +22,32 @@ public class QuestionGeneratorService { @Value("${question.json.path}") private String jsonFilePath; - private Stack types = new Stack<>(); + private Stack types = new Stack<>(); + + private JsonNode currentType; public QuestionGeneratorService(QuestionService questionService) { this.questionService = questionService; + parseQuestionTypes(); + } + + private void parseQuestionTypes() { + try { + File jsonFile = new File(jsonFilePath); + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(jsonFile); + JsonNode categories = jsonNode.findValue("categories"); + for (JsonNode category : categories) { + String categoryName = category.get("name").textValue(); + Category cat = new Category(categoryName); + JsonNode questionsNode = category.findValue("questions"); + for (JsonNode question : questionsNode) { + types.push(new QuestionType(question, cat)); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } } @Scheduled(fixedRate = 150000) @@ -39,14 +62,33 @@ public void generateQuestions() { QuestionGeneratorV2 qgen = new QuestionGeneratorV2(jsonNode); List qsp = qgen.getQuestions(Question.SPANISH); qsp.forEach(questionService::addNewQuestion); - List qen = qgen.getQuestions(Question.SPANISH); + List qen = qgen.getQuestions(Question.ENGLISH); qen.forEach(questionService::addNewQuestion); - List qfr = qgen.getQuestions(Question.SPANISH); + List qfr = qgen.getQuestions(Question.FRENCH); qfr.forEach(questionService::addNewQuestion); } catch (IOException e) { throw new RuntimeException(e); } } + private class QuestionType { + + private JsonNode question; + private Category category; + + public QuestionType(JsonNode question, Category category) { + this.question = question; + this.category = category; + } + + public JsonNode getQuestion() { + return question; + } + + public Category getCategory() { + return category; + } + } + } From 7865da53a671c4a36033587be9b4db6ccae83662 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 17:41:54 +0200 Subject: [PATCH 40/59] Deleted deprecated class --- .../components/MultipleQuestionGenerator.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 src/main/java/com/uniovi/components/MultipleQuestionGenerator.java diff --git a/src/main/java/com/uniovi/components/MultipleQuestionGenerator.java b/src/main/java/com/uniovi/components/MultipleQuestionGenerator.java deleted file mode 100644 index 7a10c2ed..00000000 --- a/src/main/java/com/uniovi/components/MultipleQuestionGenerator.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.uniovi.components; - -import com.uniovi.components.generators.QuestionGenerator; -import com.uniovi.entities.Category; -import com.uniovi.entities.Question; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class MultipleQuestionGenerator { - private QuestionGenerator[] generators; - - public MultipleQuestionGenerator(QuestionGenerator... generators) { - this.generators = generators; - } - - public List getQuestions() throws IOException { - List questions = new ArrayList<>(); - for (QuestionGenerator generator : generators) { - questions.addAll(generator.getQuestions()); - } - return questions; - } -} From 9659f1b706192654812eafc64cc4b75530ddf0d8 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 19:42:07 +0200 Subject: [PATCH 41/59] Scheduled question generation working --- .../generators/QuestionGenerator.java | 3 ++ .../generators/QuestionGeneratorV2.java | 9 ++++ src/main/java/com/uniovi/dto/QuestionDto.java | 11 ++++ .../services/QuestionGeneratorService.java | 50 +++++++++++-------- .../static/JSON/QuestionTemplates.json | 2 +- 5 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java index 6698a041..f1c01ffd 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGenerator.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGenerator.java @@ -1,5 +1,6 @@ package com.uniovi.components.generators; +import com.fasterxml.jackson.databind.JsonNode; import com.uniovi.entities.Category; import com.uniovi.entities.Question; import org.springframework.stereotype.Component; @@ -10,4 +11,6 @@ @Component public interface QuestionGenerator { List getQuestions(String language) throws IOException; + + List getQuestions(String language, JsonNode question, Category cat) throws IOException; } diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index fae0323a..239985dc 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -2,6 +2,9 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.uniovi.dto.AnswerDto; +import com.uniovi.dto.CategoryDto; +import com.uniovi.dto.QuestionDto; import com.uniovi.entities.Answer; import com.uniovi.entities.Category; import com.uniovi.entities.Question; @@ -47,6 +50,12 @@ public List getQuestions(String language) throws IOException { return questions; } + @Override + public List getQuestions(String language, JsonNode question, Category cat) throws IOException { + this.language = language; + return this.generateQuestion(question, cat); + } + private List generateQuestion(JsonNode question, Category cat) throws IOException { // Get the SPARQL query from the JSON String query = question.get("sparqlQuery").textValue(); diff --git a/src/main/java/com/uniovi/dto/QuestionDto.java b/src/main/java/com/uniovi/dto/QuestionDto.java index d97efb5f..7d4ce0e0 100644 --- a/src/main/java/com/uniovi/dto/QuestionDto.java +++ b/src/main/java/com/uniovi/dto/QuestionDto.java @@ -1,8 +1,10 @@ package com.uniovi.dto; +import com.uniovi.entities.Question; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; +import java.util.ArrayList; import java.util.List; @Getter @@ -26,4 +28,13 @@ public class QuestionDto { @Schema(description = "The language of the question") private String language; + + public QuestionDto (Question question) { + statement = question.getStatement(); + options = question.getOptions().stream().map(a -> new AnswerDto(a.getText(), a.isCorrect())).toList(); + correctAnswer = new AnswerDto(question.getCorrectAnswer().getText(), question.getCorrectAnswer().isCorrect()); + category = new CategoryDto(question.getCategory().getName(), question.getCategory().getDescription(), new ArrayList<>()); + language = question.getLanguage(); + } + } diff --git a/src/main/java/com/uniovi/services/QuestionGeneratorService.java b/src/main/java/com/uniovi/services/QuestionGeneratorService.java index 70031fe4..d7316d91 100644 --- a/src/main/java/com/uniovi/services/QuestionGeneratorService.java +++ b/src/main/java/com/uniovi/services/QuestionGeneratorService.java @@ -2,29 +2,33 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.uniovi.components.generators.QuestionGenerator; import com.uniovi.components.generators.QuestionGeneratorV2; +import com.uniovi.dto.QuestionDto; import com.uniovi.entities.Category; import com.uniovi.entities.Question; +import jakarta.transaction.Transactional; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.io.File; import java.io.IOException; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.List; -import java.util.Stack; @Service public class QuestionGeneratorService { private final QuestionService questionService; - @Value("${question.json.path}") - private String jsonFilePath; + @Value("${question.json.path:src/main/resources/static/JSON/QuestionTemplates.json}") + private String jsonFilePath = "src/main/resources/static/JSON/QuestionTemplates.json"; - private Stack types = new Stack<>(); + private Deque types = new ArrayDeque<>(); - private JsonNode currentType; + private JsonNode json; public QuestionGeneratorService(QuestionService questionService) { this.questionService = questionService; @@ -35,8 +39,8 @@ private void parseQuestionTypes() { try { File jsonFile = new File(jsonFilePath); ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(jsonFile); - JsonNode categories = jsonNode.findValue("categories"); + json = objectMapper.readTree(jsonFile); + JsonNode categories = json.findValue("categories"); for (JsonNode category : categories) { String categoryName = category.get("name").textValue(); Category cat = new Category(categoryName); @@ -51,24 +55,26 @@ private void parseQuestionTypes() { } @Scheduled(fixedRate = 150000) - public void generateQuestions() { + @Transactional + public void generateQuestions() throws IOException { + if (types.isEmpty()) { + return; + } + QuestionGenerator qgen = new QuestionGeneratorV2(json); + QuestionType type = types.pop(); + List questions; - File jsonFile = new File(jsonFilePath); + List qsp = qgen.getQuestions(Question.SPANISH, type.getQuestion(), type.getCategory()); + questions = qsp.stream().map(QuestionDto::new).toList(); + questions.forEach(questionService::addNewQuestion); - ObjectMapper objectMapper = new ObjectMapper(); + List qen = qgen.getQuestions(Question.ENGLISH, type.getQuestion(), type.getCategory()); + questions = qen.stream().map(QuestionDto::new).toList(); + questions.forEach(questionService::addNewQuestion); - try { - JsonNode jsonNode = objectMapper.readTree(jsonFile); - QuestionGeneratorV2 qgen = new QuestionGeneratorV2(jsonNode); - List qsp = qgen.getQuestions(Question.SPANISH); - qsp.forEach(questionService::addNewQuestion); - List qen = qgen.getQuestions(Question.ENGLISH); - qen.forEach(questionService::addNewQuestion); - List qfr = qgen.getQuestions(Question.FRENCH); - qfr.forEach(questionService::addNewQuestion); - } catch (IOException e) { - throw new RuntimeException(e); - } + List qfr = qgen.getQuestions(Question.FRENCH, type.getQuestion(), type.getCategory()); + questions = qfr.stream().map(QuestionDto::new).toList(); + questions.forEach(questionService::addNewQuestion); } private class QuestionType { diff --git a/src/main/resources/static/JSON/QuestionTemplates.json b/src/main/resources/static/JSON/QuestionTemplates.json index c6323b0d..825176a9 100644 --- a/src/main/resources/static/JSON/QuestionTemplates.json +++ b/src/main/resources/static/JSON/QuestionTemplates.json @@ -89,7 +89,7 @@ ], "question": "elementLabel", "answer": "atomicNumber", - "sparqlQuery": "select distinct ?element ?[QUESTION] ?[ANSWER] where {\n ?element wdt:P31 wd:Q11344 .\n ?element wdt:P1086 ?[ANSWER] .\n ?element rdfs:label ?[QUESTION] .\n FILTER NOT EXISTS {?element wdt:P31 wd:Q1299291} .\n FILTER(LANG(?[QUESTION])=\"es\")\n }" + "sparqlQuery": "select distinct ?element ?[QUESTION] ?[ANSWER] where {\n ?element wdt:P31 wd:Q11344 .\n ?element wdt:P1086 ?[ANSWER] .\n ?element rdfs:label ?[QUESTION] .\n FILTER NOT EXISTS {?element wdt:P31 wd:Q1299291} .\n FILTER(LANG(?[QUESTION])=\"[LANGUAGE]\")\n }" } ] } From e848907ecf13687bf36a3b81f20ddedb6f644745 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 20:07:05 +0200 Subject: [PATCH 42/59] Fixed correct question not being associated with the question --- src/main/java/com/uniovi/entities/Associations.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/uniovi/entities/Associations.java b/src/main/java/com/uniovi/entities/Associations.java index 73218e2f..bb35ebd0 100644 --- a/src/main/java/com/uniovi/entities/Associations.java +++ b/src/main/java/com/uniovi/entities/Associations.java @@ -110,6 +110,9 @@ public static class QuestionAnswers { public static void addAnswer(Question question, List answer) { for (Answer a : answer) { a.setQuestion(question); + if (a.isCorrect()) { + question.setCorrectAnswer(a); + } } question.getOptions().addAll(answer); } @@ -125,6 +128,7 @@ public static void removeAnswer(Question question, List answer) { for (Answer a : answer) { a.setQuestion(null); } + question.setCorrectAnswer(null); } //public static void removeAnswer(Question question, List answer) { // question.getOptions().remove(answer); From 5346fe0021cec9f6c650acf21b8d22947f8b3be5 Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 20:42:07 +0200 Subject: [PATCH 43/59] Fixed SampleDataService and tests --- .../services/InsertSampleDataService.java | 111 ++++++------------ .../services/QuestionGeneratorService.java | 28 ++++- src/test/java/com/uniovi/Wiq_UnitTests.java | 60 +--------- 3 files changed, 66 insertions(+), 133 deletions(-) diff --git a/src/main/java/com/uniovi/services/InsertSampleDataService.java b/src/main/java/com/uniovi/services/InsertSampleDataService.java index cc158cd8..f22b1aa8 100644 --- a/src/main/java/com/uniovi/services/InsertSampleDataService.java +++ b/src/main/java/com/uniovi/services/InsertSampleDataService.java @@ -1,6 +1,5 @@ package com.uniovi.services; -import com.uniovi.components.MultipleQuestionGenerator; import com.uniovi.dto.PlayerDto; import com.uniovi.entities.Question; import com.uniovi.repositories.GameSessionRepository; @@ -19,81 +18,37 @@ @Service public class InsertSampleDataService { -// private final PlayerService playerService; -// private final QuestionService questionService; -// private final CategoryService categoryService; -// private final QuestionRepository questionRepository; -// private final GameSessionRepository gameSessionRepository; -// private Environment environment; -// -// private Logger log = LoggerFactory.getLogger(InsertSampleDataService.class); -// -//// public InsertSampleDataService(PlayerService playerService, QuestionService questionService, -//// CategoryService categoryService, QuestionRepository questionRepository, -//// GameSessionRepository gameSessionRepository, Environment environment) { -//// this.playerService = playerService; -//// this.questionService = questionService; -//// this.categoryService = categoryService; -//// this.questionRepository = questionRepository; -//// this.gameSessionRepository = gameSessionRepository; -//// this.environment = environment; -//// } -//// -//// @Transactional -//// @EventListener(ApplicationReadyEvent.class) // Uncomment this line to insert sample data on startup -//// public void insertSampleQuestions() throws InterruptedException, IOException { -//// if (!playerService.getUserByEmail("test@test.com").isPresent()) { -//// PlayerDto player = new PlayerDto(); -//// player.setEmail("test@test.com"); -//// player.setUsername("test"); -//// player.setPassword("test"); -//// player.setRoles(new String[]{"ROLE_USER"}); -//// playerService.generateApiKey(playerService.addNewPlayer(player)); -//// } -//// -//// if (Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("test")))) { -//// log.info("Test profile active, skipping sample data insertion"); -//// return; -//// } -//// -//// generateSampleData(); -//// } -//// -//// @Transactional -//// public void generateTestQuestions() { -//// questionRepository.deleteAll(); -//// questionService.testQuestions(4); -//// } -//// -//// @Transactional -//// public void generateSampleData() throws InterruptedException, IOException { -//// -//// questionRepository.deleteAll(); -//// -//// MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( -//// new ContinentQuestionGeneration(categoryService, Question.ENGLISH), -//// new CapitalQuestionGenerator(categoryService, Question.ENGLISH), -//// new BorderQuestionGenerator(categoryService, Question.ENGLISH) -//// ); -//// List questionsEn = allQuestionGenerator.getQuestions(); -//// questionsEn.forEach(questionService::addNewQuestion); -//// -//// allQuestionGenerator = new MultipleQuestionGenerator( -//// new ContinentQuestionGeneration(categoryService, Question.SPANISH), -//// new CapitalQuestionGenerator(categoryService, Question.SPANISH), -//// new BorderQuestionGenerator(categoryService, Question.SPANISH) -//// ); -//// List questionsEs = allQuestionGenerator.getQuestions(); -//// questionsEs.forEach(questionService::addNewQuestion); -//// -//// allQuestionGenerator = new MultipleQuestionGenerator( -//// new ContinentQuestionGeneration(categoryService, Question.FRENCH), -//// new CapitalQuestionGenerator(categoryService, Question.FRENCH), -//// new BorderQuestionGenerator(categoryService, Question.FRENCH) -//// ); -//// List questionsFr = allQuestionGenerator.getQuestions(); -//// questionsFr.forEach(questionService::addNewQuestion); -//// -//// log.info("Sample questions inserted"); -//// } + private final PlayerService playerService; + private final QuestionService questionService; + private final CategoryService categoryService; + private final QuestionRepository questionRepository; + private final GameSessionRepository gameSessionRepository; + private Environment environment; + + private Logger log = LoggerFactory.getLogger(InsertSampleDataService.class); + + public InsertSampleDataService(PlayerService playerService, QuestionService questionService, + CategoryService categoryService, QuestionRepository questionRepository, + GameSessionRepository gameSessionRepository, Environment environment) { + this.playerService = playerService; + this.questionService = questionService; + this.categoryService = categoryService; + this.questionRepository = questionRepository; + this.gameSessionRepository = gameSessionRepository; + this.environment = environment; + } + + @Transactional + @EventListener(ApplicationReadyEvent.class) // Uncomment this line to insert sample data on startup + public void insertSampleQuestions() throws InterruptedException, IOException { + if (!playerService.getUserByEmail("test@test.com").isPresent()) { + PlayerDto player = new PlayerDto(); + player.setEmail("test@test.com"); + player.setUsername("test"); + player.setPassword("test"); + player.setRoles(new String[]{"ROLE_USER"}); + playerService.generateApiKey(playerService.addNewPlayer(player)); + } + } + } \ No newline at end of file diff --git a/src/main/java/com/uniovi/services/QuestionGeneratorService.java b/src/main/java/com/uniovi/services/QuestionGeneratorService.java index d7316d91..e443c6f8 100644 --- a/src/main/java/com/uniovi/services/QuestionGeneratorService.java +++ b/src/main/java/com/uniovi/services/QuestionGeneratorService.java @@ -8,13 +8,18 @@ import com.uniovi.entities.Category; import com.uniovi.entities.Question; import jakarta.transaction.Transactional; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.io.File; import java.io.IOException; import java.util.ArrayDeque; +import java.util.Arrays; import java.util.Deque; import java.util.List; @@ -23,13 +28,17 @@ public class QuestionGeneratorService { private final QuestionService questionService; - @Value("${question.json.path:src/main/resources/static/JSON/QuestionTemplates.json}") private String jsonFilePath = "src/main/resources/static/JSON/QuestionTemplates.json"; private Deque types = new ArrayDeque<>(); private JsonNode json; + @Autowired + private Environment environment; + + private Logger log = LoggerFactory.getLogger(InsertSampleDataService.class); + public QuestionGeneratorService(QuestionService questionService) { this.questionService = questionService; parseQuestionTypes(); @@ -60,6 +69,12 @@ public void generateQuestions() throws IOException { if (types.isEmpty()) { return; } + + if (Arrays.stream(environment.getActiveProfiles()).anyMatch(env -> (env.equalsIgnoreCase("test")))) { + log.info("Test profile active, skipping sample data insertion"); + return; + } + QuestionGenerator qgen = new QuestionGeneratorV2(json); QuestionType type = types.pop(); List questions; @@ -77,6 +92,17 @@ public void generateQuestions() throws IOException { questions.forEach(questionService::addNewQuestion); } + @Transactional + public void generateTestQuestions() throws IOException { + QuestionGenerator qgen = new QuestionGeneratorV2(json); + QuestionType type = types.pop(); + List questions; + + List qsp = qgen.getQuestions(Question.SPANISH, type.getQuestion(), type.getCategory()); + questions = qsp.stream().map(QuestionDto::new).toList(); + questions.forEach(questionService::addNewQuestion); + } + private class QuestionType { private JsonNode question; diff --git a/src/test/java/com/uniovi/Wiq_UnitTests.java b/src/test/java/com/uniovi/Wiq_UnitTests.java index 1e397366..40c29b69 100644 --- a/src/test/java/com/uniovi/Wiq_UnitTests.java +++ b/src/test/java/com/uniovi/Wiq_UnitTests.java @@ -2,9 +2,6 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import com.uniovi.components.generators.geography.BorderQuestionGenerator; -import com.uniovi.components.generators.geography.CapitalQuestionGenerator; -import com.uniovi.components.generators.geography.ContinentQuestionGeneration; import com.uniovi.entities.*; import com.uniovi.services.*; import org.junit.jupiter.api.*; @@ -13,15 +10,13 @@ import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; +import java.io.IOException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; -import static org.junit.Assert.*; -import static org.junit.jupiter.api.Assertions.assertNotNull; - @SpringBootTest @Tag("unit") @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -38,6 +33,8 @@ public class Wiq_UnitTests { private CategoryService categoryService; @Autowired private InsertSampleDataService sampleDataService; + @Autowired + private QuestionGeneratorService questionGeneratorService; private Player createPlayer(){ return new Player("name","test@email.com","password"); @@ -48,57 +45,12 @@ public void testPlayerService() { List players = playerService.getUsersByRole("ROLE_USER"); Assertions.assertEquals(1, players.size()); } - @Test - @Order(2) - public void testQuestions(){ - sampleDataService.insertSampleQuestions(); - sampleDataService.generateSampleData(); - List questions = questionService.getAllQuestions(); - Assertions.assertFalse(questions.isEmpty()); - - } - @Test - @Order(2) - public void testRandomQuestions(){ - sampleDataService.insertSampleQuestions(); - sampleDataService.generateSampleData(); - List questions = questionService.getRandomQuestions(5); - Assertions.assertEquals(5,questions.size()); - } @Test @Order(3) - public void testBorderQuestionsGenerator(){ - BorderQuestionGenerator borderQuestionGenerator=new BorderQuestionGenerator(categoryService,Question.SPANISH); - List questions = borderQuestionGenerator.getQuestions(); - Assertions.assertFalse(questions.isEmpty()); - - for (Question question : questions) { - Assertions.assertNotNull(question.getCorrectAnswer()); - Assertions.assertEquals(4, question.getOptions().size()); - Assertions.assertTrue(question.getOptions().contains(question.getCorrectAnswer())); - } - } - - @Test - @Order(4) - public void testCapitalQuestionsGenerator(){ - CapitalQuestionGenerator capitalQuestionGenerator=new CapitalQuestionGenerator(categoryService,Question.SPANISH); - List questions = capitalQuestionGenerator.getQuestions(); - Assertions.assertFalse(questions.isEmpty()); - - for (Question question : questions) { - Assertions.assertNotNull(question.getCorrectAnswer()); - Assertions.assertEquals(4, question.getOptions().size()); - Assertions.assertTrue(question.getOptions().contains(question.getCorrectAnswer())); - } - } - - @Test - @Order(5) - public void testContinentQuestionsGenerator(){ - ContinentQuestionGeneration continentQuestionGenerator=new ContinentQuestionGeneration(categoryService,Question.SPANISH); - List questions = continentQuestionGenerator.getQuestions(); + public void testQuestionsGenerator() throws IOException { + questionGeneratorService.generateTestQuestions(); + List questions = questionService.getAllQuestions(); Assertions.assertFalse(questions.isEmpty()); for (Question question : questions) { From 047bf0fcd4311549fed27f2c818b792ebde1786d Mon Sep 17 00:00:00 2001 From: uo287545 Date: Thu, 25 Apr 2024 22:19:08 +0200 Subject: [PATCH 44/59] Fixed unit tests --- .../generators/QuestionGeneratorV2.java | 3 - src/main/java/com/uniovi/dto/AnswerDto.java | 1 + src/main/java/com/uniovi/dto/CategoryDto.java | 1 + .../services/QuestionGeneratorService.java | 1 - src/test/java/com/uniovi/Wiq_UnitTests.java | 122 +++--------------- 5 files changed, 22 insertions(+), 106 deletions(-) diff --git a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java index 239985dc..efb1d8f6 100644 --- a/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java +++ b/src/main/java/com/uniovi/components/generators/QuestionGeneratorV2.java @@ -91,9 +91,6 @@ private List generateQuestion(JsonNode question, Category cat) throws // Generate the question Question q = new Question(questionStatement, options, correct, cat, language); - // Scramble the options - q.scrambleOptions(); - // Add the question to the list questions.add(q); } diff --git a/src/main/java/com/uniovi/dto/AnswerDto.java b/src/main/java/com/uniovi/dto/AnswerDto.java index 026eede6..304ee640 100644 --- a/src/main/java/com/uniovi/dto/AnswerDto.java +++ b/src/main/java/com/uniovi/dto/AnswerDto.java @@ -6,6 +6,7 @@ @Getter @Setter @NoArgsConstructor +@AllArgsConstructor @ToString public class AnswerDto { diff --git a/src/main/java/com/uniovi/dto/CategoryDto.java b/src/main/java/com/uniovi/dto/CategoryDto.java index fc87530e..57aef22e 100644 --- a/src/main/java/com/uniovi/dto/CategoryDto.java +++ b/src/main/java/com/uniovi/dto/CategoryDto.java @@ -11,6 +11,7 @@ @Getter @Setter @NoArgsConstructor +@AllArgsConstructor public class CategoryDto { @Schema(description = "The name of the category", example = "Geography") diff --git a/src/main/java/com/uniovi/services/QuestionGeneratorService.java b/src/main/java/com/uniovi/services/QuestionGeneratorService.java index e443c6f8..7c2d36c7 100644 --- a/src/main/java/com/uniovi/services/QuestionGeneratorService.java +++ b/src/main/java/com/uniovi/services/QuestionGeneratorService.java @@ -11,7 +11,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.core.env.Environment; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; diff --git a/src/test/java/com/uniovi/Wiq_UnitTests.java b/src/test/java/com/uniovi/Wiq_UnitTests.java index 46ff6a25..2fde133f 100644 --- a/src/test/java/com/uniovi/Wiq_UnitTests.java +++ b/src/test/java/com/uniovi/Wiq_UnitTests.java @@ -1,44 +1,22 @@ package com.uniovi; -import com.uniovi.dto.*; -import com.uniovi.entities.*; -import com.uniovi.repositories.*; -import com.uniovi.services.*; -import com.uniovi.services.impl.*; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; -import com.uniovi.components.generators.geography.BorderQuestionGenerator; -import com.uniovi.components.generators.geography.CapitalQuestionGenerator; -import com.uniovi.components.generators.geography.ContinentQuestionGeneration; +import com.uniovi.dto.PlayerDto; +import com.uniovi.dto.RoleDto; import com.uniovi.entities.*; +import com.uniovi.repositories.*; import com.uniovi.services.*; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; -import org.junit.Assert; -import org.junit.jupiter.api.*; -import org.springframework.beans.factory.annotation.Autowired; -import com.uniovi.dto.*; -import com.uniovi.entities.*; -import com.uniovi.repositories.*; -import com.uniovi.services.*; -import com.uniovi.services.impl.*; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; -import java.io.IOException; -import java.awt.print.Pageable; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; import java.io.IOException; import java.net.URI; import java.net.URLEncoder; @@ -49,13 +27,6 @@ import java.time.LocalDateTime; import java.util.*; -import static org.junit.Assert.*; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - @SpringBootTest @Tag("unit") @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -96,9 +67,10 @@ public class Wiq_UnitTests { private final HttpClient httpClient = HttpClient.newHttpClient(); - private Player createPlayer(){ - return new Player("name","test@email.com","password"); + private Player createPlayer() { + return new Player("name", "test@email.com", "password"); } + @Test @Order(1) public void testPlayerService() { @@ -106,67 +78,11 @@ public void testPlayerService() { Assertions.assertEquals(1, players.size()); } - @Test - @Order(2) - public void testQuestions() throws InterruptedException, IOException { - sampleDataService.insertSampleQuestions(); - sampleDataService.generateSampleData(); @Order(3) public void testQuestionsGenerator() throws IOException { questionGeneratorService.generateTestQuestions(); List questions = questionService.getAllQuestions(); Assertions.assertFalse(questions.isEmpty()); - - } - @Test - @Order(2) - public void testRandomQuestions() throws InterruptedException, IOException { - sampleDataService.insertSampleQuestions(); - sampleDataService.generateSampleData(); - List questions = questionService.getRandomQuestions(5); - Assertions.assertEquals(5,questions.size()); - } - - @Test - @Order(3) - public void testBorderQuestionsGenerator() throws InterruptedException, IOException { - BorderQuestionGenerator borderQuestionGenerator=new BorderQuestionGenerator(categoryService,Question.SPANISH); - List questions = borderQuestionGenerator.getQuestions(); - Assertions.assertFalse(questions.isEmpty()); - - for (Question question : questions) { - Assertions.assertNotNull(question.getCorrectAnswer()); - Assertions.assertEquals(4, question.getOptions().size()); - Assertions.assertTrue(question.getOptions().contains(question.getCorrectAnswer())); - } - } - - @Test - @Order(4) - public void testCapitalQuestionsGenerator() throws InterruptedException, IOException { - CapitalQuestionGenerator capitalQuestionGenerator=new CapitalQuestionGenerator(categoryService,Question.SPANISH); - List questions = capitalQuestionGenerator.getQuestions(); - Assertions.assertFalse(questions.isEmpty()); - - for (Question question : questions) { - Assertions.assertNotNull(question.getCorrectAnswer()); - Assertions.assertEquals(4, question.getOptions().size()); - Assertions.assertTrue(question.getOptions().contains(question.getCorrectAnswer())); - } - } - - @Test - @Order(5) - public void testContinentQuestionsGenerator() throws InterruptedException, IOException { - ContinentQuestionGeneration continentQuestionGenerator=new ContinentQuestionGeneration(categoryService,Question.SPANISH); - List questions = continentQuestionGenerator.getQuestions(); - Assertions.assertFalse(questions.isEmpty()); - - for (Question question : questions) { - Assertions.assertNotNull(question.getCorrectAnswer()); - Assertions.assertEquals(4, question.getOptions().size()); - Assertions.assertTrue(question.getOptions().contains(question.getCorrectAnswer())); - } } @Test @@ -393,6 +309,7 @@ public void testGetDuration() { Assertions.assertEquals("00:05:00", gameSession.getDuration()); } + @Test @Order(22) public void testPlayerToJson() { @@ -460,8 +377,7 @@ public void testScrambleOptions() { question.addOption(option2); question.addOption(option3); - question.scrambleOptions(); - List scrambledOptions = question.getOptions(); + List scrambledOptions = question.returnScrambledOptions(); Assertions.assertTrue(scrambledOptions.contains(option1)); Assertions.assertTrue(scrambledOptions.contains(option2)); @@ -661,7 +577,7 @@ public void testCreatePlayerValid() throws IOException, InterruptedException, JS data.put("username", "newUser"); data.put("email", "newUser@email.com"); data.put("password", "password"); - data.put("roles", new String[] {"ROLE_USER"}); + data.put("roles", new String[]{"ROLE_USER"}); HttpResponse response = sendRequest("POST", "/api/players", Map.of("API-KEY", apiKey.getKeyToken()), data); @@ -884,7 +800,7 @@ public void testGetQuestionsByCategoryName() throws IOException, InterruptedExce ApiKey apiKey = player.getApiKey(); HttpResponse response = sendRequest("GET", "/api/questions", Map.of(), - Map.of("apiKey", apiKey.getKeyToken(), "category", "Geography")); + Map.of("apiKey", apiKey.getKeyToken(), "category", "Science")); Assertions.assertEquals(200, response.statusCode()); JSONObject json = parseJsonResponse(response); @@ -898,7 +814,7 @@ public void testGetQuestionsByCategoryId() throws IOException, InterruptedExcept insertSomeQuestions(); Player player = playerService.getUsersByRole("ROLE_USER").get(0); ApiKey apiKey = player.getApiKey(); - Category cat = categoryService.getCategoryByName("Geography"); + Category cat = categoryService.getCategoryByName("Science"); HttpResponse response = sendRequest("GET", "/api/questions", Map.of(), Map.of("apiKey", apiKey.getKeyToken(), "category", cat.getId())); @@ -1564,17 +1480,18 @@ public void testDeleteQuestion() throws IOException, InterruptedException, JSONE /** * Sends an HTTP request to the API - * @param method HTTP method - * @param uri URI to send the request to + * + * @param method HTTP method + * @param uri URI to send the request to * @param headers Headers to include in the request - * @param data Data to send in the request + * @param data Data to send in the request * @return The response from the server * @throws IOException * @throws InterruptedException */ private HttpResponse sendRequest(String method, String uri, - Map headers, - Map data) throws IOException, InterruptedException { + Map headers, + Map data) throws IOException, InterruptedException { HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); uri = Wiq_IntegrationTests.URL.substring(0, Wiq_IntegrationTests.URL.length() - 1) + uri; @@ -1603,6 +1520,7 @@ private HttpResponse sendRequest(String method, String uri, /** * Builds a query string from a map of data + * * @param data The data to include in the query string * @return The query string */ @@ -1615,6 +1533,7 @@ private String buildQueryString(Map data) { /** * Parses the JSON response from the server + * * @param response The response from the server * @return The JSON object * @throws JSONException @@ -1627,7 +1546,6 @@ private JSONObject parseJsonResponse(HttpResponse response) throws JSONE * Inserts some sample questions into the database */ private void insertSomeQuestions() throws InterruptedException, IOException { - List qs = new ContinentQuestionGeneration(categoryService, Question.SPANISH).getQuestions(); - qs.forEach(questionService::addNewQuestion); + questionGeneratorService.generateTestQuestions(); } } From 8f4f72d6e651741953d75cb1830af31fc6e0370c Mon Sep 17 00:00:00 2001 From: uo287545 Date: Fri, 26 Apr 2024 01:44:32 +0200 Subject: [PATCH 45/59] All tests working --- .../QuestionGeneratorTestController.java | 35 ------------------- .../services/QuestionGeneratorService.java | 11 +++++- src/main/resources/application.properties | 4 --- src/test/java/com/uniovi/Wiq_UnitTests.java | 12 ++++--- src/test/java/com/uniovi/steps/GameStep.java | 11 ++++-- 5 files changed, 25 insertions(+), 48 deletions(-) delete mode 100644 src/main/java/com/uniovi/components/QuestionGeneratorTestController.java diff --git a/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java b/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java deleted file mode 100644 index 77ee4aa2..00000000 --- a/src/main/java/com/uniovi/components/QuestionGeneratorTestController.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.uniovi.components; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.uniovi.components.generators.QuestionGeneratorV2; -import com.uniovi.entities.Question; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.io.File; -import java.io.IOException; -import java.util.List; - -@RestController -public class QuestionGeneratorTestController { - - private final String jsonFilePath = "src/main/resources/static/JSON/QuestionTemplates.json"; - - @RequestMapping("/test") - public void test() throws IOException { - // Crear un objeto File con la ruta del archivo JSON - File jsonFile = new File(jsonFilePath); - - // Crear un ObjectMapper de Jackson - ObjectMapper objectMapper = new ObjectMapper(); - - // Leer el archivo JSON y convertirlo en un JsonNode - JsonNode jsonNode = objectMapper.readTree(jsonFile); - QuestionGeneratorV2 qgen = new QuestionGeneratorV2(jsonNode); - List q = qgen.getQuestions(Question.SPANISH); - for(Question question : q){ - System.out.println(question); - } - } -} diff --git a/src/main/java/com/uniovi/services/QuestionGeneratorService.java b/src/main/java/com/uniovi/services/QuestionGeneratorService.java index 7c2d36c7..253a87db 100644 --- a/src/main/java/com/uniovi/services/QuestionGeneratorService.java +++ b/src/main/java/com/uniovi/services/QuestionGeneratorService.java @@ -5,6 +5,7 @@ import com.uniovi.components.generators.QuestionGenerator; import com.uniovi.components.generators.QuestionGeneratorV2; import com.uniovi.dto.QuestionDto; +import com.uniovi.entities.Answer; import com.uniovi.entities.Category; import com.uniovi.entities.Question; import jakarta.transaction.Transactional; @@ -27,7 +28,7 @@ public class QuestionGeneratorService { private final QuestionService questionService; - private String jsonFilePath = "src/main/resources/static/JSON/QuestionTemplates.json"; + public static final String jsonFilePath = "src/main/resources/static/JSON/QuestionTemplates.json"; private Deque types = new ArrayDeque<>(); @@ -102,6 +103,14 @@ public void generateTestQuestions() throws IOException { questions.forEach(questionService::addNewQuestion); } + @Transactional + public void generateTestQuestions(String cat) throws IOException { + Answer a1 = new Answer("1", true); + List answers = List.of(a1, new Answer("2", false), new Answer("3", false), new Answer("4", false)); + Question q = new Question("Statement", answers, a1, new Category(cat), "es"); + questionService.addNewQuestion(new QuestionDto(q)); + } + private class QuestionType { private JsonNode question; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 44108bf6..563c3468 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -17,7 +17,3 @@ springdoc.packagesToScan=com.uniovi.controllers.api management.endpoint.metrics.enabled=true management.endpoints.web.exposure.include=prometheus management.endpoints.jmx.exposure.include=* - - -# Question templates -question.json.path=src/main/resources/static/JSON/QuestionTemplates.json \ No newline at end of file diff --git a/src/test/java/com/uniovi/Wiq_UnitTests.java b/src/test/java/com/uniovi/Wiq_UnitTests.java index 2fde133f..b370fdea 100644 --- a/src/test/java/com/uniovi/Wiq_UnitTests.java +++ b/src/test/java/com/uniovi/Wiq_UnitTests.java @@ -795,12 +795,13 @@ public void testGetQuestions() throws IOException, InterruptedException, JSONExc @Test @Order(51) public void testGetQuestionsByCategoryName() throws IOException, InterruptedException, JSONException { - insertSomeQuestions(); + String cat = "Science"; + questionGeneratorService.generateTestQuestions(cat); Player player = playerService.getUsersByRole("ROLE_USER").get(0); ApiKey apiKey = player.getApiKey(); HttpResponse response = sendRequest("GET", "/api/questions", Map.of(), - Map.of("apiKey", apiKey.getKeyToken(), "category", "Science")); + Map.of("apiKey", apiKey.getKeyToken(), "category", cat)); Assertions.assertEquals(200, response.statusCode()); JSONObject json = parseJsonResponse(response); @@ -811,10 +812,11 @@ public void testGetQuestionsByCategoryName() throws IOException, InterruptedExce @Test @Order(52) public void testGetQuestionsByCategoryId() throws IOException, InterruptedException, JSONException { - insertSomeQuestions(); + String category = "Science"; + questionGeneratorService.generateTestQuestions(category); Player player = playerService.getUsersByRole("ROLE_USER").get(0); ApiKey apiKey = player.getApiKey(); - Category cat = categoryService.getCategoryByName("Science"); + Category cat = categoryService.getCategoryByName(category); HttpResponse response = sendRequest("GET", "/api/questions", Map.of(), Map.of("apiKey", apiKey.getKeyToken(), "category", cat.getId())); @@ -1545,7 +1547,7 @@ private JSONObject parseJsonResponse(HttpResponse response) throws JSONE /** * Inserts some sample questions into the database */ - private void insertSomeQuestions() throws InterruptedException, IOException { + private void insertSomeQuestions() throws IOException { questionGeneratorService.generateTestQuestions(); } } diff --git a/src/test/java/com/uniovi/steps/GameStep.java b/src/test/java/com/uniovi/steps/GameStep.java index deaad33f..bc430547 100644 --- a/src/test/java/com/uniovi/steps/GameStep.java +++ b/src/test/java/com/uniovi/steps/GameStep.java @@ -2,6 +2,7 @@ import com.uniovi.Wiq_IntegrationTests; import com.uniovi.services.InsertSampleDataService; +import com.uniovi.services.QuestionGeneratorService; import com.uniovi.util.PropertiesExtractor; import com.uniovi.util.SeleniumUtils; import io.cucumber.java.en.Then; @@ -12,23 +13,27 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import java.io.IOException; import java.util.List; public class GameStep extends Wiq_IntegrationTests { @Autowired private InsertSampleDataService dataService; + @Autowired + private QuestionGeneratorService questionGeneratorService; + private Logger log = LoggerFactory.getLogger(GameStep.class); @When("I press Play") - public void iPressPlay() { - dataService.generateTestQuestions(); + public void iPressPlay() throws IOException { + questionGeneratorService.generateTestQuestions(); List elems = SeleniumUtils.waitLoadElementsBy(driver, "free", "//*[@href=\"/game\"]", 5); elems.get(0).click(); } @Then("I should start playing") - public void iShouldStartPlaying() throws InterruptedException { + public void iShouldStartPlaying() { boolean playing = true; String xpath = "//*[contains(text(),'" + p.getString("game.finish", PropertiesExtractor.getSPANISH()) + "')]"; int i= 0; From 62f56186583c014dc89214342aa7b3133516a4cc Mon Sep 17 00:00:00 2001 From: uo287545 Date: Fri, 26 Apr 2024 01:59:11 +0200 Subject: [PATCH 46/59] Removed unused code --- .../com/uniovi/services/QuestionService.java | 11 +------ .../services/impl/QuestionServiceImpl.java | 33 +------------------ 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/uniovi/services/QuestionService.java b/src/main/java/com/uniovi/services/QuestionService.java index 7eb7d422..b482cfd6 100644 --- a/src/main/java/com/uniovi/services/QuestionService.java +++ b/src/main/java/com/uniovi/services/QuestionService.java @@ -3,11 +3,10 @@ import com.uniovi.dto.QuestionDto; import com.uniovi.entities.Category; import com.uniovi.entities.Question; -import jakarta.transaction.Transactional; import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import org.springframework.data.domain.Pageable; import java.util.List; import java.util.Optional; @@ -97,12 +96,4 @@ public interface QuestionService { * @param id The id of the question to delete */ void deleteQuestion(Long id); - - /** - * Get some test questions - * - * @param num The number of questions to get - * @return The questions selected - */ - List testQuestions(int num); } diff --git a/src/main/java/com/uniovi/services/impl/QuestionServiceImpl.java b/src/main/java/com/uniovi/services/impl/QuestionServiceImpl.java index f0ec9f7e..f92f7958 100644 --- a/src/main/java/com/uniovi/services/impl/QuestionServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/QuestionServiceImpl.java @@ -12,20 +12,16 @@ import com.uniovi.services.QuestionService; import jakarta.persistence.EntityManager; import jakarta.transaction.Transactional; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.querydsl.QPageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.security.SecureRandom; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Random; -import org.springframework.data.domain.Pageable; @Service public class QuestionServiceImpl implements QuestionService { @@ -169,31 +165,4 @@ public void deleteQuestion(Long id) { questionRepository.delete(question); } } - - @Override - public List testQuestions(int num) { - List res = new ArrayList<>(); - Category c = new Category("Test category", "Test category"); - categoryService.addNewCategory(c); - for (int i = 0; i < num; i++) { - Question q = new Question(); - q.setStatement("Test question " + i); - q.setLanguage(LocaleContextHolder.getLocale().getLanguage()); - Associations.QuestionsCategory.addCategory(q, c); - List answers = new ArrayList<>(); - for (int j = 0; j < 4; j++) { - Answer a = new Answer(); - a.setText("Test answer " + j); - a.setCorrect(j == 0); - if(j==0) q.setCorrectAnswer(a); - answerService.addNewAnswer(a); - answers.add(a); - } - Associations.QuestionAnswers.addAnswer(q, answers); - addNewQuestion(q); - res.add(q); - } - return res; - } - } From a49cc531146685aa2aeebf1ecb7d50d4cf18f1aa Mon Sep 17 00:00:00 2001 From: uo287545 Date: Fri, 26 Apr 2024 02:19:24 +0200 Subject: [PATCH 47/59] Trying to fix the game controller test --- src/test/java/com/uniovi/steps/GameStep.java | 2 +- src/test/resources/features/Game.feature | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/uniovi/steps/GameStep.java b/src/test/java/com/uniovi/steps/GameStep.java index bc430547..820a1217 100644 --- a/src/test/java/com/uniovi/steps/GameStep.java +++ b/src/test/java/com/uniovi/steps/GameStep.java @@ -40,7 +40,7 @@ public void iShouldStartPlaying() { List finalMessage; while(playing){ //I obtain the buttons for the answers - List elems = SeleniumUtils.waitLoadElementsBy(driver, "text", "Test answer 0", 10); + List elems = By.cssSelector(".container .row button").findElements(driver); log.info("Found " + elems.size() + " buttons"); log.info("Iteration " + i + " of the game"); //I click on the first button diff --git a/src/test/resources/features/Game.feature b/src/test/resources/features/Game.feature index e970154c..b3120c41 100644 --- a/src/test/resources/features/Game.feature +++ b/src/test/resources/features/Game.feature @@ -6,4 +6,4 @@ Feature: I try to play a normal game And I press the register button And I go to the home page When I press Play - #Then I should start playing \ No newline at end of file + Then I should start playing \ No newline at end of file From ee0ae97247e4678cfa53d06aca24efa7ee10a313 Mon Sep 17 00:00:00 2001 From: Pelayori <31128562+Pelayori@users.noreply.github.com> Date: Fri, 26 Apr 2024 02:25:54 +0200 Subject: [PATCH 48/59] Finish user management --- .../uniovi/configuration/SecurityConfig.java | 2 +- .../uniovi/controllers/PlayersController.java | 111 ++++++++++++++++- .../services/InsertSampleDataService.java | 20 ++-- .../com/uniovi/services/PlayerService.java | 13 ++ .../java/com/uniovi/services/RoleService.java | 6 + .../services/impl/PlayerServiceImpl.java | 11 ++ .../uniovi/services/impl/RoleServiceImpl.java | 7 ++ src/main/resources/messages.properties | 11 ++ src/main/resources/messages_en.properties | 21 ++++ src/main/resources/messages_es.properties | 23 +++- src/main/resources/messages_fr.properties | 21 ++++ src/main/resources/static/css/admin.css | 4 + src/main/resources/static/css/custom.css | 46 +++++++ src/main/resources/static/css/nav.css | 2 +- .../resources/static/script/adminModals.js | 112 ++++++++++++++++++ .../templates/fragments/adminModals.html | 76 ++++++++++++ .../templates/player/admin/admin.html | 3 +- .../player/admin/userManagement.html | 38 ++++-- 18 files changed, 501 insertions(+), 26 deletions(-) create mode 100644 src/main/resources/static/script/adminModals.js create mode 100644 src/main/resources/templates/fragments/adminModals.html diff --git a/src/main/java/com/uniovi/configuration/SecurityConfig.java b/src/main/java/com/uniovi/configuration/SecurityConfig.java index 674cd83f..068364b0 100644 --- a/src/main/java/com/uniovi/configuration/SecurityConfig.java +++ b/src/main/java/com/uniovi/configuration/SecurityConfig.java @@ -48,7 +48,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/api/**").permitAll() .requestMatchers("/game/**").authenticated() .requestMatchers("/ranking/playerRanking").authenticated() - .requestMatchers("/admin/**").hasAuthority("ROLE_ADMIN") + .requestMatchers("/player/admin/**").hasAuthority("ROLE_ADMIN") .requestMatchers("/**").permitAll() ).formLogin( form -> form diff --git a/src/main/java/com/uniovi/controllers/PlayersController.java b/src/main/java/com/uniovi/controllers/PlayersController.java index afbc33c1..c9fb5ff9 100644 --- a/src/main/java/com/uniovi/controllers/PlayersController.java +++ b/src/main/java/com/uniovi/controllers/PlayersController.java @@ -1,42 +1,52 @@ package com.uniovi.controllers; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.uniovi.configuration.SecurityConfig; +import com.uniovi.dto.RoleDto; +import com.uniovi.entities.Associations; import com.uniovi.entities.GameSession; import com.uniovi.entities.Player; +import com.uniovi.entities.Role; import com.uniovi.services.GameSessionService; import com.uniovi.services.PlayerService; +import com.uniovi.services.RoleService; import com.uniovi.validators.SignUpValidator; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.*; import com.uniovi.dto.PlayerDto; -import org.springframework.web.bind.annotation.ModelAttribute; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; import java.security.Principal; import java.util.Optional; +import java.util.List; @Controller public class PlayersController { private final PlayerService playerService; + private final RoleService roleService; private final SignUpValidator signUpValidator; private final GameSessionService gameSessionService; @Autowired - public PlayersController(PlayerService playerService, SignUpValidator signUpValidator, GameSessionService gameSessionService) { + public PlayersController(PlayerService playerService, SignUpValidator signUpValidator, GameSessionService gameSessionService, + RoleService roleService) { this.playerService = playerService; this.signUpValidator = signUpValidator; this.gameSessionService = gameSessionService; + this.roleService = roleService; } @GetMapping("/signup") @@ -140,6 +150,97 @@ public String showUserManagementFragment(Model model, Pageable pageable) { return "player/admin/userManagement"; } + @GetMapping("/player/admin/deleteUser") + @ResponseBody + public String deleteUser(HttpServletResponse response, @RequestParam String username, Principal principal) { + Player player = playerService.getUserByUsername(username).orElse(null); + if (player == null) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "User not found"; + } + + if (principal.getName().equals(player.getUsername())) { + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + return "You can't delete yourself"; + } + + playerService.deletePlayer(player.getId()); + return "User deleted"; + } + + @GetMapping("/player/admin/changePassword") + @ResponseBody + public String changePassword(HttpServletResponse response, @RequestParam String username, @RequestParam String password) { + Player player = playerService.getUserByUsername(username).orElse(null); + if (player == null) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "User not found"; + } + + playerService.updatePassword(player, password); + return "User password changed"; + } + + @GetMapping("/player/admin/getRoles") + @ResponseBody + public String getRoles(@RequestParam String username) { + List roles = roleService.getAllRoles(); + Player player = playerService.getUserByUsername(username).orElse(null); + + roles.remove(roleService.getRole("ROLE_USER")); + + if (player == null) { + return "{}"; + } + + ObjectMapper mapper = new ObjectMapper(); + ObjectNode rolesJson = mapper.createObjectNode(); + for (Role role : roles) { + boolean hasRole = player.getRoles().contains(role); + rolesJson.put(role.getName(), hasRole); + } + + return rolesJson.toString(); + } + + @GetMapping("/player/admin/changeRoles") + @ResponseBody + public String changeRoles(HttpServletResponse response, @RequestParam String username, @RequestParam String roles) { + Player player = playerService.getUserByUsername(username).orElse(null); + if (player == null) { + response.setStatus(HttpServletResponse.SC_NOT_FOUND); + return "User not found"; + } + + JsonNode rolesJson; + try { + rolesJson = new ObjectMapper().readTree(roles); + } catch (Exception e) { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "Invalid roles"; + } + + rolesJson.fieldNames().forEachRemaining(roleName -> { + boolean hasRole = rolesJson.get(roleName).asBoolean(); + + Role role = roleService.getRole(roleName); + if (role == null && !hasRole) { + return; + } else if (role == null) { + role = roleService.addRole(new RoleDto(roleName)); + } + + if (hasRole) { + Associations.PlayerRole.addRole(player, role); + } else { + Associations.PlayerRole.removeRole(player, role); + } + }); + + playerService.savePlayer(player); + return "User roles changed"; + } + @GetMapping("/player/admin/questionManagement") public String showQuestionManagementFragment() { return "player/admin/questionManagement"; diff --git a/src/main/java/com/uniovi/services/InsertSampleDataService.java b/src/main/java/com/uniovi/services/InsertSampleDataService.java index d5415fc7..456aab2d 100644 --- a/src/main/java/com/uniovi/services/InsertSampleDataService.java +++ b/src/main/java/com/uniovi/services/InsertSampleDataService.java @@ -80,15 +80,15 @@ public void generateSampleData() throws InterruptedException, IOException { questionRepository.deleteAll(); - MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( - //new ContinentQuestionGeneration(categoryService, Question.ENGLISH), - //new CapitalQuestionGenerator(categoryService, Question.ENGLISH), - //new BorderQuestionGenerator(categoryService, Question.ENGLISH) - ); - List questionsEn = allQuestionGenerator.getQuestions(); - questionsEn.forEach(questionService::addNewQuestion); + //MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( + // //new ContinentQuestionGeneration(categoryService, Question.ENGLISH), + // //new CapitalQuestionGenerator(categoryService, Question.ENGLISH), + // //new BorderQuestionGenerator(categoryService, Question.ENGLISH) + //); + //List questionsEn = allQuestionGenerator.getQuestions(); + //questionsEn.forEach(questionService::addNewQuestion); - allQuestionGenerator = new MultipleQuestionGenerator( + MultipleQuestionGenerator allQuestionGenerator = new MultipleQuestionGenerator( //new ContinentQuestionGeneration(categoryService, Question.SPANISH), //new CapitalQuestionGenerator(categoryService, Question.SPANISH), new BorderQuestionGenerator(categoryService, Question.SPANISH) @@ -101,8 +101,8 @@ public void generateSampleData() throws InterruptedException, IOException { // new CapitalQuestionGenerator(categoryService, Question.FRENCH), // new BorderQuestionGenerator(categoryService, Question.FRENCH) //); - List questionsFr = allQuestionGenerator.getQuestions(); - questionsFr.forEach(questionService::addNewQuestion); + //List questionsFr = allQuestionGenerator.getQuestions(); + //questionsFr.forEach(questionService::addNewQuestion); log.info("Sample questions inserted"); } diff --git a/src/main/java/com/uniovi/services/PlayerService.java b/src/main/java/com/uniovi/services/PlayerService.java index 0cf320a2..fc9da433 100644 --- a/src/main/java/com/uniovi/services/PlayerService.java +++ b/src/main/java/com/uniovi/services/PlayerService.java @@ -81,4 +81,17 @@ public interface PlayerService { * @return A page with all the players */ Page getPlayersPage(Pageable pageable); + + /** + * Update the password of a player + * @param player The player to update the password + * @param password The new password + */ + void updatePassword(Player player, String password); + + /** + * Save a player in the database + * @param player The player to save + */ + void savePlayer(Player player); } diff --git a/src/main/java/com/uniovi/services/RoleService.java b/src/main/java/com/uniovi/services/RoleService.java index e620105f..fd196940 100644 --- a/src/main/java/com/uniovi/services/RoleService.java +++ b/src/main/java/com/uniovi/services/RoleService.java @@ -20,4 +20,10 @@ public interface RoleService { * @return The role with the given name */ Role getRole(String name); + + /** + * Get all the roles in the database + * @return A list with all the roles + */ + List getAllRoles(); } diff --git a/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java b/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java index d3b868a4..9d0fb497 100644 --- a/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/PlayerServiceImpl.java @@ -143,4 +143,15 @@ public void deletePlayer(Long id) { public Page getPlayersPage(Pageable pageable) { return playerRepository.findAll(pageable); } + + @Override + public void updatePassword(Player player, String password) { + player.setPassword(passwordEncoder.encode(password)); + playerRepository.save(player); + } + + @Override + public void savePlayer(Player player) { + playerRepository.save(player); + } } diff --git a/src/main/java/com/uniovi/services/impl/RoleServiceImpl.java b/src/main/java/com/uniovi/services/impl/RoleServiceImpl.java index b10bbcc1..bec8464c 100644 --- a/src/main/java/com/uniovi/services/impl/RoleServiceImpl.java +++ b/src/main/java/com/uniovi/services/impl/RoleServiceImpl.java @@ -35,4 +35,11 @@ public Role addRole(RoleDto role) { public Role getRole(String name) { return roleRepository.findById(name).orElse(null); } + + @Override + public List getAllRoles() { + List roles = new ArrayList<>(); + roleRepository.findAll().forEach(roles::add); + return roles; + } } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 7130729c..dde5f6c0 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -123,6 +123,17 @@ admin.section.user.management=Administración de usuarios admin.section.question.management=Administración de preguntas role.label=Roles user.details=Acciones +admin.user.delete=Eliminar usuario +admin.user.delete.title=Confirmar borrado de usuario +admin.user.delete.message=¿Está seguro de que desea eliminar este usuario?\nTodos los datos asociados con esta cuenta se eliminarán.\nLa acción es irreversible. +admin.changepassword=Cambiar contraseña +admin.changeroles=Modificar roles +modal.password.title=Confirmar cambio de contraseña para +admin.password.change.input=Nueva contraseña +admin.roles.change=Confirmar cambio de roles para +modal.new.role=Nuevo rol +modal.close=Cerrar +modal.confirm=Confirmar # -------------------Statements for the page management--------------------- page.first=Primera diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 901ef79b..538ec9ee 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -118,4 +118,25 @@ game.points=Points: game.currentQuestion=Question: game.finish=The game has finished. Your score is: +# -------------------Statements for the admin section--------------------- +admin.section.user.management=Users management +admin.section.question.management=Questions management +role.label=Roles +user.details=Details +admin.user.delete=Delete user +admin.user.delete.title=Confirm deleting user +admin.user.delete.message=Are you sure you want to delete this user?\nAll data associated with this account will be erased\nThis action cannot be undone +admin.changepassword=Change password +admin.changeroles=Modify roles +modal.password.title=Confirm password change for +admin.password.change.input=New password +admin.roles.change=Confirm role change for +modal.new.role=New role +modal.close=Close +modal.confirm=Save changes + +# -------------------Statements for the page management--------------------- +page.first=First +page.last=Last + diff --git a/src/main/resources/messages_es.properties b/src/main/resources/messages_es.properties index 61bf6b83..8445a750 100644 --- a/src/main/resources/messages_es.properties +++ b/src/main/resources/messages_es.properties @@ -117,4 +117,25 @@ game.continue=Siguiente pregunta answer.correct=La respuesta correcta era: game.points=Puntos: game.currentQuestion=Pregunta: -game.finish=El juego ha terminado. Tu puntuación ha sido: \ No newline at end of file +game.finish=El juego ha terminado. Tu puntuación ha sido: + +# -------------------Statements for the admin section--------------------- +admin.section.user.management=Administración de usuarios +admin.section.question.management=Administración de preguntas +role.label=Roles +user.details=Acciones +admin.user.delete=Eliminar usuario +admin.user.delete.title=Confirmar borrado de usuario +admin.user.delete.message=¿Está seguro de que desea eliminar este usuario?\nTodos los datos asociados con esta cuenta se eliminarán.\nLa acción es irreversible. +admin.changepassword=Cambiar contraseña +admin.changeroles=Modificar roles +modal.password.title=Confirmar cambio de contraseña para +admin.password.change.input=Nueva contraseña +admin.roles.change=Confirmar cambio de roles para +modal.new.role=Nuevo rol +modal.close=Cerrar +modal.confirm=Confirmar + +# -------------------Statements for the page management--------------------- +page.first=Primera +page.last=Última \ No newline at end of file diff --git a/src/main/resources/messages_fr.properties b/src/main/resources/messages_fr.properties index 616c23b8..1722bb01 100644 --- a/src/main/resources/messages_fr.properties +++ b/src/main/resources/messages_fr.properties @@ -113,3 +113,24 @@ game.points=Points: game.currentQuestion=Question: game.finish=Le jeu est terminé. Votre score est : +# -------------------Déclarations pour la section administrateur--------------------- +admin.section.user.management=Gestion des utilisateurs +admin.section.question.management=Gestion des questions +role.label=Rôles +user.details=Actions +admin.user.delete=Supprimer l'utilisateur +admin.user.delete.title=Confirmer la suppression de l'utilisateur +admin.user.delete.message=Êtes-vous sûr de vouloir supprimer cet utilisateur ?\nToutes les données associées à ce compte seront supprimées.\nL'action est irréversible. +admin.changepassword=Changer le mot de passe +admin.changeroles=Modifier les rôles +modal.password.title=Confirmer le changement de mot de passe pour +admin.password.change.input=Nouveau mot de passe +admin.roles.change=Confirmer le changement de rôles pour +modal.new.role=Nouveau rôle +modal.close=Fermer +modal.confirm=Confirmer + +# -------------------Déclarations pour la gestion de la page--------------------- +page.first=Première +page.last=Dernière + diff --git a/src/main/resources/static/css/admin.css b/src/main/resources/static/css/admin.css index a797f39b..db24eb8e 100644 --- a/src/main/resources/static/css/admin.css +++ b/src/main/resources/static/css/admin.css @@ -19,4 +19,8 @@ .separator { border-bottom: 1px solid white; margin: 10px 0; +} + +.text-danger-light { + color: #ff5e5e; } \ No newline at end of file diff --git a/src/main/resources/static/css/custom.css b/src/main/resources/static/css/custom.css index 9d7cb489..679d7a7e 100644 --- a/src/main/resources/static/css/custom.css +++ b/src/main/resources/static/css/custom.css @@ -76,4 +76,50 @@ footer { .button-container a { flex: 1; margin: 0 5px; +} + +.modal { + color: black; +} + +.modal .btn.btn-primary { + background-color: #007bff; + border-color: #007bff; +} + +.btn-close { + box-sizing: content-box; + width: 1em; + height: 1em; + padding: .25em .25em; + color: #000; + background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; + border: 0; + border-radius: .25rem; + opacity: .5 +} + +.btn-close:hover { + color: #000; + text-decoration: none; + opacity: .75 +} + +.btn-close:focus { + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25); + opacity: 1 +} + +.btn-close.disabled, +.btn-close:disabled { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + opacity: .25 +} + +.modal-body { + white-space: pre; } \ No newline at end of file diff --git a/src/main/resources/static/css/nav.css b/src/main/resources/static/css/nav.css index 79c8ca3c..102f4e28 100644 --- a/src/main/resources/static/css/nav.css +++ b/src/main/resources/static/css/nav.css @@ -18,7 +18,7 @@ /* Estilo para los desplegables */ .dropdown-menu { color: #fff; - background-color: black; + background-color: rgb(19, 19, 19); border: 2px solid #fff; } diff --git a/src/main/resources/static/script/adminModals.js b/src/main/resources/static/script/adminModals.js new file mode 100644 index 00000000..aa468c2e --- /dev/null +++ b/src/main/resources/static/script/adminModals.js @@ -0,0 +1,112 @@ +function setupUserEvents() { + $("#deleteUserAdminModal").on('show.bs.modal', function (event) { + let button = $(event.relatedTarget); + let username = button.attr('data-bs-username'); + $(".modal-title b").text('"' + username + '"'); + $("#deleteModalConfirm").attr('data-bs-username', username); + }); + + $("#deleteModalConfirm").click(function () { + let username = $(this).attr('data-bs-username'); + $.ajax({ + url: "/player/admin/deleteUser", + type: "GET", + data: { + username: username + }, + success: function (data) { + $('#tab-content').load('/player/admin/userManagement'); + $("#deleteUserAdminModal").modal('hide'); + } + }); + }); + + $("#changePasswordAdminModal").on('show.bs.modal', function (event) { + let button = $(event.relatedTarget); + let username = button.attr('data-bs-username'); + $(".modal-title b").text('"' + username + '"'); + $("#changePasswordConfirm").attr('data-bs-username', username); + }); + + $("#changePasswordConfirm").click(function () { + let username = $(this).attr('data-bs-username'); + let newPass = $("#changePasswordInput").val(); + $.ajax({ + url: "/player/admin/changePassword", + type: "GET", + data: { + username: username, + password: newPass + }, + success: function (data) { + $('#tab-content').load('/player/admin/userManagement'); + $("#changePasswordAdminModal").modal('hide'); + } + }); + }); + + $("#changeRolesAdminModal").on('show.bs.modal', function (event) { + let button = $(event.relatedTarget); + let username = button.attr('data-bs-username'); + $(".modal-title b").text('"' + username + '"'); + $("#changeRolesConfirm").attr('data-bs-username', username); + $.ajax({ + url: "/player/admin/getRoles", + type: "GET", + data: { + username: username + }, + success: function (data) { + let roles = JSON.parse(data); + let rolesContainer = $("#rolesContainer"); + rolesContainer.empty(); + let i = 0; + for (const role in roles) { + let hasRole = roles[role]; + let div = $('
'); + let input = $(''); + let label = $(''); + div.append(input); + div.append(label); + rolesContainer.append(div); + i = i + 1; + } + }, + error: function (data) { + alert("Error: " + data); + } + }); + }); + + $("#changeRolesConfirm").click(function () { + let username = $(this).attr('data-bs-username'); + + let allRoles = $("#rolesContainer input"); + let roles = {}; + allRoles.each(function() { + roles[$(this).val()] = $(this).is(':checked'); + }); + let newRoleInput = $("#newRole").val(); + if (newRoleInput !== "") { + roles[newRoleInput] = true; + } + + let rolesString = JSON.stringify(roles); + + $.ajax({ + url: "/player/admin/changeRoles", + type: "GET", + data: { + username: username, + roles: rolesString + }, + success: function (data) { + $('#tab-content').load('/player/admin/userManagement'); + $("#changeRolesAdminModal").modal('hide'); + }, + error: function (data) { + alert("Error: " + data); + } + }); + }); +} \ No newline at end of file diff --git a/src/main/resources/templates/fragments/adminModals.html b/src/main/resources/templates/fragments/adminModals.html new file mode 100644 index 00000000..d5c19e74 --- /dev/null +++ b/src/main/resources/templates/fragments/adminModals.html @@ -0,0 +1,76 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/player/admin/admin.html b/src/main/resources/templates/player/admin/admin.html index 27b2b915..bf185e25 100644 --- a/src/main/resources/templates/player/admin/admin.html +++ b/src/main/resources/templates/player/admin/admin.html @@ -8,7 +8,7 @@ -
+