generated from Arquisoft/wiq_0
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #96 from Arquisoft/question-generation
First version of the question generator
- Loading branch information
Showing
23 changed files
with
843 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
src/main/java/com/uniovi/components/QuestionGeneratorTestController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.uniovi.components; | ||
|
||
import com.uniovi.components.generators.geography.CapitalQuestionGenerator; | ||
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.util.List; | ||
|
||
@RestController | ||
public class QuestionGeneratorTestController { | ||
|
||
@Autowired | ||
CapitalQuestionGenerator qgen; | ||
|
||
@RequestMapping("/test") | ||
public void test() { | ||
List<Question> q = qgen.getQuestions(); | ||
for(Question question : q){ | ||
System.out.println(question); | ||
} | ||
} | ||
} |
88 changes: 88 additions & 0 deletions
88
src/main/java/com/uniovi/components/generators/AbstractQuestionGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
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; | ||
|
||
public abstract class AbstractQuestionGenerator implements QuestionGenerator{ | ||
|
||
private List<Question> questions = new ArrayList<>(); | ||
protected final CategoryService categoryService; | ||
private String query; | ||
protected String statement; | ||
|
||
protected AbstractQuestionGenerator(CategoryService categoryService) { | ||
this.categoryService = categoryService; | ||
} | ||
|
||
public void questionGenerator(String statement, List<String> options, String correctAnswer, Category category){ | ||
List<Answer> 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); | ||
question.scrambleOptions(); | ||
questions.add(question); | ||
} | ||
|
||
public List<Question> getQuestions() { | ||
HttpClient client = HttpClient.newHttpClient(); | ||
try { | ||
|
||
String endpointUrl = "https://query.wikidata.org/sparql?query=" + | ||
URLEncoder.encode(this.getQuery(), StandardCharsets.UTF_8.toString()) + | ||
"&format=json"; | ||
|
||
HttpRequest request = HttpRequest.newBuilder() | ||
.uri(URI.create(endpointUrl)) | ||
.header("Accept", "application/json") | ||
.build(); | ||
|
||
HttpResponse<String> 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<String> options = this.generateOptions(resultsNode, result); | ||
String correctAnswer = this.generateCorrectAnswer(result); | ||
String statement = this.getQuestionSubject(result); | ||
questionGenerator(statement, options, correctAnswer, this.getCategory()); | ||
|
||
} | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
|
||
return questions; | ||
} | ||
|
||
protected abstract List<String> generateOptions(JsonNode results, JsonNode result); | ||
protected abstract String generateCorrectAnswer(JsonNode result); | ||
|
||
protected abstract String getQuestionSubject(JsonNode result); | ||
|
||
} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/uniovi/components/generators/QuestionGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.uniovi.components.generators; | ||
|
||
import com.uniovi.entities.Category; | ||
import com.uniovi.entities.Question; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.List; | ||
|
||
@Component | ||
public interface QuestionGenerator { | ||
|
||
String getQuery(); | ||
List<Question> getQuestions(); | ||
|
||
Category getCategory(); | ||
|
||
|
||
} |
17 changes: 17 additions & 0 deletions
17
src/main/java/com/uniovi/components/generators/geography/AbstractGeographyGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
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"); | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
src/main/java/com/uniovi/components/generators/geography/BorderQuestionGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
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 Set<String> usedCountries = new HashSet<>(); | ||
|
||
public BorderQuestionGenerator(CategoryService categoryService) { | ||
super(categoryService); | ||
this.statement = "Which countries share a border with "; | ||
} | ||
|
||
private List<String> getAllBorderingCountries(JsonNode resultsNode, String correctCountry) { | ||
List<String> 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<String> selectRandomIncorrectBorderingCountries(List<String> allBorderingCountries, String correctCountry, int count) { | ||
List<String> incorrectBorderingCountries = new ArrayList<>(); | ||
Random random = new Random(); | ||
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<String> 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],en\" }" + | ||
"}"; | ||
} | ||
} |
72 changes: 72 additions & 0 deletions
72
src/main/java/com/uniovi/components/generators/geography/CapitalQuestionGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package com.uniovi.components.generators.geography; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.uniovi.services.CategoryService; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Random; | ||
|
||
@Component | ||
public class CapitalQuestionGenerator extends AbstractGeographyGenerator{ | ||
|
||
public CapitalQuestionGenerator(CategoryService categoryService) { | ||
super(categoryService); | ||
this.statement = "What is the capital of "; | ||
} | ||
|
||
@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],en\" }" + | ||
"}" + | ||
"ORDER BY ?countryLabel"; | ||
} | ||
|
||
private List<String> getAllCapitals(JsonNode resultsNode, String correctCapital) { | ||
// Obtener todas las capitales del JSON (distintas a la capital correcta) | ||
List<String> 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<String> selectRandomIncorrectCapitals(List<String> allCapitals, String correctCapital, int count) { | ||
List<String> incorrectCapitals = new ArrayList<>(); | ||
Random random = new Random(); | ||
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<String> 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() + "?"; | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
src/main/java/com/uniovi/components/generators/geography/ContinentQuestionGeneration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package com.uniovi.components.generators.geography; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.uniovi.services.CategoryService; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Random; | ||
|
||
public class ContinentQuestionGeneration extends AbstractGeographyGenerator{ | ||
public ContinentQuestionGeneration(CategoryService categoryService) { | ||
super(categoryService); | ||
this.statement = "In which continent is "; | ||
} | ||
|
||
private List<String> getAllContinents(JsonNode resultsNode, String correctContinent) { | ||
// Obtener todas las capitales del JSON (distintas a la capital correcta) | ||
List<String> 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<String> selectRandomIncorrectContinents(List<String> allContinents, String correctContinent, int count) { | ||
List<String> incorrectContinents = new ArrayList<>(); | ||
Random random = new Random(); | ||
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<String> 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],en\" }" + | ||
"}" + | ||
"ORDER BY ?countryLabel"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.uniovi.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
public class AnswerDto { | ||
private Long id; | ||
private String text; | ||
private boolean correct; | ||
|
||
} |
Oops, something went wrong.