Skip to content

Commit

Permalink
3 new categories added. Queries and processing optimized
Browse files Browse the repository at this point in the history
to reduce waiting between questions
questions
  • Loading branch information
ChristianFN2 committed Apr 2, 2024
1 parent 05599e6 commit c49ce91
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 20 deletions.
30 changes: 30 additions & 0 deletions gatewayservice/gateway-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,36 @@ app.get('/imgs/cities/question', async (req, res) => {
}
});

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

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

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

app.post('/imgs/answer', async (req, res) => {
try {
const answer = req.body.answer;
Expand Down
105 changes: 89 additions & 16 deletions questionservice/question-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class WIQ_API{
imgToAssociatedMap = new Map()

//Num of fetched items
const itemsNum = 100
const itemsNum = 200

//Required by wikidata to accept the request
const headers = new Headers();
Expand All @@ -50,16 +50,37 @@ class WIQ_API{
for (let i = 0; i < numOfChosen; i++) {
this.#getRandomNumNotInSetAndUpdate(itemsNum, chosenNums)
}

const associates = []
const imgs = []
for(var i=0;i<numOfChosen;i++){
imgs.push(data.results.bindings[chosenNums[i]].image.value)
associates.push(data.results.bindings[chosenNums[i]].itemLabel.value)
imgToAssociatedMap.set(imgs[i], associates[i])
let finalChosenLabels = []
//I filter in case the label does not have a proper name
//and just a wikidata identifier (Q followed by numbers)
const regex = /^Q\d+$/
while(regex.test(data.results.bindings[chosenNums[0]].itemLabel.value)){
this.#getRandomNumNotInSetAndUpdate(itemsNum,chosenNums)
chosenNums[0] = chosenNums.pop()
}
finalChosenLabels.push(data.results.bindings[chosenNums[0]].itemLabel.value);
for(let i=0;i<numOfChosen-1;i++){
//I check if there are repeated labels
//(More efficient than in the query) and if it is a proper label
while(finalChosenLabels.includes(data.results.bindings[chosenNums[i+1]].itemLabel.value)
|| regex.test(data.results.bindings[chosenNums[i+1]].itemLabel.value)){
this.#getRandomNumNotInSetAndUpdate(itemsNum, chosenNums)
chosenNums[i+1] = chosenNums.pop()
}
finalChosenLabels.push(data.results.bindings[chosenNums[i+1]].itemLabel.value)
}

let counter = chosenNums.length
while(chosenNums.length>0){
imgs.push(data.results.bindings[chosenNums.pop()].image.value)
associates.push(finalChosenLabels.pop())
imgToAssociatedMap.set(imgs[counter], associates[counter])
counter--
}

chosenNums = []
//Choose a random item of the chosen to make the question
const chosenNum = this.#getRandomNumNotInSetAndUpdate(numOfChosen,chosenNums)
const chosenAssociate = associates[chosenNum]
Expand Down Expand Up @@ -98,8 +119,8 @@ app.get('/imgs/flags/question', async (req, res) => {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item wdt:P31 wd:Q6256;
wdt:P41 ?image.
FILTER NOT EXISTS { ?item wdt:P41 wd:Q3024110 }
}`
}
LIMIT 200`
const question = JSON.parse(await wiq.getQuestionAndImages(query,"flags","belongs to"));
res.json(question);
});
Expand All @@ -112,14 +133,66 @@ app.get('/imgs/flags/question', async (req, res) => {
*/
app.get('/imgs/cities/question', async (req, res) => {
//Gets city images and their associated names
const query = `SELECT ?item ?itemLabel ?image WHERE
{
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item wdt:P31 wd:Q515;
const query = `SELECT ?item ?itemLabel ?image WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item wdt:P31 wd:Q515.
?item wdt:P18 ?image.
}
LIMIT 200`
const question = JSON.parse(await wiq.getQuestionAndImages(query,"imagen","corresponds to"));
res.json(question);
});

/**
* Returns the needed information to construct a question of the form
* "Which of the following images corresponds to xMonument?" with 4 options
* @param {} req - Not used
* @param {Object} res - Contains the question (question) and the monuments (images)
*/
app.get('/imgs/monuments/question', async (req, res) => {
//Gets monument images and their associated names
const query = `SELECT ?item ?itemLabel ?image WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item wdt:P31 wd:Q4989906;
wdt:P18 ?image.
FILTER NOT EXISTS { ?item wdt:P41 wd:Q3024110. }
}
LIMIT 100`
}
LIMIT 200`
const question = JSON.parse(await wiq.getQuestionAndImages(query,"images","corresponds to"));
res.json(question);
});

/**
* Returns the needed information to construct a question of the form
* "Which of the following tourist attractions corresponds to xTouristAttraction?" with 4 options
* @param {} req - Not used
* @param {Object} res - Contains the question (question) and the tourist attractions (images)
*/
app.get('/imgs/tourist_attractions/question', async (req, res) => {
//Gets attractions images and their associated names
const query = `SELECT ?item ?itemLabel ?image WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item wdt:P31 wd:Q570116;
wdt:P18 ?image.
}
LIMIT 200`
const question = JSON.parse(await wiq.getQuestionAndImages(query,"images","corresponds to"));
res.json(question);
});

/**
* Returns the needed information to construct a question of the form
* "Which of the following images corresponds to xFood?" with 4 options
* @param {} req - Not used
* @param {Object} res - Contains the question (question) and the foods (images)
*/
app.get('/imgs/foods/question', async (req, res) => {
//Gets food images and their associated names
const query = `SELECT ?item ?itemLabel ?image WHERE {
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
?item wdt:P31 wd:Q8195619;
wdt:P18 ?image.
}
LIMIT 200`
const question = JSON.parse(await wiq.getQuestionAndImages(query,"images","corresponds to"));
res.json(question);
});
Expand Down
36 changes: 32 additions & 4 deletions webapp/src/components/Game.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import Question from "./Question";
const Game = () => {
const [flagGameStarted, setFlagGameStarted] = useState(false);
const [cityGameStarted, setCityGameStarted] = useState(false);
const [monumentGameStarted, setMonumentGameStarted] = useState(false);
const [touristAttractionGameStarted, setTouristAttractionGameStarted] = useState(false);
const [foodGameStarted, setFoodGameStarted] = useState(false);
const isAuthenticated = useIsAuthenticated();
const navigate = useNavigate();
const auth = useAuthUser();
Expand All @@ -16,6 +19,15 @@ const Game = () => {
const startCitiesGame = () => {
setCityGameStarted(!cityGameStarted);
};
const startMonumentsGame = () => {
setMonumentGameStarted(!monumentGameStarted);
};
const startTouristAttractionsGame = () => {
setTouristAttractionGameStarted(!touristAttractionGameStarted);
};
const startFoodsGame = () => {
setFoodGameStarted(!foodGameStarted);
};
useEffect(() => {
if (!isAuthenticated()) {
navigate("/login");
Expand All @@ -24,21 +36,37 @@ const Game = () => {

return (
<div>
{isAuthenticated()? (flagGameStarted || cityGameStarted) ?(
{isAuthenticated()? (flagGameStarted || cityGameStarted || monumentGameStarted
|| touristAttractionGameStarted || foodGameStarted) ?(
<div>
{flagGameStarted && <Question type="imgs" category="flags"/>}
{cityGameStarted && <Question type="imgs" category="cities"/>}
{monumentGameStarted && <Question type="imgs" category="monuments"/>}
{touristAttractionGameStarted && <Question type="imgs" category="tourist_attractions"/>}
{foodGameStarted && <Question type="imgs" category="foods"/>}
</div>
) : (
<div className="flex flex-col items-center justify-center mt-16">
<h1 className="text-6xl font-bold text-zinc-700">{auth.username}, Let's Play!</h1>
<h1 className="text-6xl font-bold text-zinc-700">{auth.username}, Let's Play! Guess the...</h1>
<button onClick={startFlagsGame} className="mt-10 border border-blue-500 text-blue-500 font-bold text-2xl py-2 px-4 rounded-full
transition-transform transform-gpu hover:scale-105">
Guess the flag
Flag
</button>
<button onClick={startCitiesGame} className="mt-10 border border-blue-500 text-blue-500 font-bold text-2xl py-2 px-4 rounded-full
transition-transform transform-gpu hover:scale-105">
Guess the city
City
</button>
<button onClick={startMonumentsGame} className="mt-10 border border-blue-500 text-blue-500 font-bold text-2xl py-2 px-4 rounded-full
transition-transform transform-gpu hover:scale-105">
Monument
</button>
<button onClick={startTouristAttractionsGame} className="mt-10 border border-blue-500 text-blue-500 font-bold text-2xl py-2 px-4 rounded-full
transition-transform transform-gpu hover:scale-105">
Tourist attraction
</button>
<button onClick={startFoodsGame} className="mt-10 border border-blue-500 text-blue-500 font-bold text-2xl py-2 px-4 rounded-full
transition-transform transform-gpu hover:scale-105">
Food
</button>
</div>
):""}
Expand Down

0 comments on commit c49ce91

Please sign in to comment.