Skip to content

Commit

Permalink
Added question service and linked it with the gateway service
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianFN2 committed Mar 6, 2024
1 parent 0461995 commit 20874f0
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 0 deletions.
21 changes: 21 additions & 0 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const port = 8000;

const authServiceUrl = process.env.AUTH_SERVICE_URL || 'http://localhost:8002';
const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001';
const questionServiceUrl = process.env.QUESTION_SERVICE_URL || 'http://localhost:8010';

app.use(cors());
app.use(express.json());
Expand Down Expand Up @@ -41,6 +42,26 @@ app.post('/adduser', async (req, res) => {
}
});

app.get('/flags/question', async (req, res) => {
try {
// Forward the request to the question service
const questionResponse = await axios.get(questionServiceUrl+'/flags/question', req.body);
res.json(questionResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
}
});

app.get('/flags/answer', async (req, res) => {
try {
// Forward the request to the question service
const questionResponse = await axios.get(questionServiceUrl+'/flags/answer', req.body);
res.json(questionResponse.data);
} catch (error) {
res.status(error.response.status).json({ error: error.response.data.error });
}
});

// Start the gateway service
const server = app.listen(port, () => {
console.log(`Gateway Service listening at http://localhost:${port}`);
Expand Down
20 changes: 20 additions & 0 deletions questionservice/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions questionservice/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"wikibase-sdk": "^8.1.1"
}
}
126 changes: 126 additions & 0 deletions questionservice/question-service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
const WBK = require('wikibase-sdk')
const wbk = WBK({
instance: 'https://www.wikidata.org',
sparqlEndpoint: 'https://query.wikidata.org/sparql' // Required to use `sparqlQuery` and `getReverseClaims` functions, optional otherwise
})
const express = require('express');
const app = express();
const port = 8010;

app.use(express.static('public'));

app.use(express.text());

//Correct image
var correctAnswerFlag
//Associates flags with their countries
var flagToCountryMap = new Map()

class WIQ_API{
/**
*
* @returns JSON with the question and the flags
*/
async getQuestionAndCountryFlags() {
//Reset the map for the new question
flagToCountryMap = new Map()

//Num of fetched countries
const countriesNum = 100

//Required by wikidata to accept the request
const headers = new Headers();
headers.append('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
+' AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36');

const sparql = `SELECT ?país ?paísLabel ?imagen_de_la_bandera WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?país wdt:P31 wd:Q6256.
OPTIONAL { ?país wdt:P41 ?imagen_de_la_bandera. }
}
LIMIT ${countriesNum}`

//Constructing the url for the wikidata request
var url = wbk.sparqlQuery(sparql);

const response = await fetch(url, { headers });
const data = await response.json()

var chosenNums = [];
const numOfChosen = 4
// Generate n random numbers
for (let i = 0; i < numOfChosen; i++) {
this.#getRandomNumNotInSetAndUpdate(countriesNum, chosenNums)
}

const countries = []
const imgs = []
for(var i=0;i<numOfChosen;i++){
//Making sure there is an image associated
while(!'imagen_de_la_bandera' in data.results.bindings[chosenNums[i]]){
chosenNums[i] = this.#getRandomNumNotInSetAndUpdate(countriesNum, chosenNums)
}
imgs.push(data.results.bindings[chosenNums[i]].imagen_de_la_bandera.value)
countries.push(data.results.bindings[chosenNums[i]].paísLabel.value)
flagToCountryMap.set(imgs[i], countries[i])
}

chosenNums = []
//Choose a random country of the chosen to make the question
const chosenCountry = countries[this.#getRandomNumNotInSetAndUpdate(numOfChosen,chosenNums)]

const questionAndFlags = {
question: `Which of the following flags belongs to ${chosenCountry}?`,
flags: [`${imgs[0]}`,`${imgs[1]}`,`${imgs[2]}`,`${imgs[3]}`]
}

return JSON.stringify(questionAndFlags)
}

#getRandomNumNotInSetAndUpdate(numLimit, set){
let randomNumber;
do {
randomNumber = Math.floor(Math.random() * numLimit);
} while (set.includes(randomNumber)); // Ensure the number is unique
set.push(randomNumber);
return randomNumber
}
}

const wiq = new WIQ_API()

/**
* Returns the needed information to construct a question of the form
* "Which of the following flags belongs to (insert country)?" with 4 options
* @param {} req - Not used
* @param {Object} res - Contains the question (question) and the images of the flags (flags)
*/
app.get('flags/question', async (req, res) => {
const question = await wiq.getQuestionAndCountryFlags()
res.json(question);
});

/**
* Gets a response indicating if the chosen flag img was correct or not
* @param {string} req - Flag img url selected by the player
* @param {Object} res - JSON containing whether the answer was correct "true"
* or not "false". In case it was incorrect, the chosen
* country will be returned as well
*/
app.get('flags/answer', (req, res) => {
const answeredFlag = req.body
if(correctAnswerFlag==answeredFlag){
res.json({
correct: "true"
})
} else {
res.json({
correct: "false",
country: `${flagToCountryMap.get(answeredFlag)}`
})
}
});

app.listen(port, () => {
console.log(`Questions service listening on http://localhost:${port}`);
});

0 comments on commit 20874f0

Please sign in to comment.