Reputation: 193
I'm trying to build a geography game/quiz using the Google Maps API and the REST Countries API as well. I have the Google Maps functionality working along with the REST Countries API as well. What's happening is, on each page refresh, a random country loads and data from the REST Countries API generates (it's hidden so the user will only get hints as to what country it is). The map also pans to the center of the random country(hybrid image only with no country label). This is exactly what I want to happen.
I have a loop in my Javascript pulling countries (answers) for the multiple choice section but it's only pulling from the beginning. Is there a way to randomize the label and insert the correct answer (countryData.name) in there somewhere? I had this working but my code was not dry at all and the first selection was always the right answer. Not sure how to get the loop to pull answers at random either. This is the last thing I need to do before I can start styling and fixing the point system. Sorry, had to hide my Google API key.
const countriesList = document.getElementById("countries");
let gameTitle = document.querySelector(".gameTitle");
let selectedCountry;
let updateScore = document.querySelector(".score");
let guesses = document.querySelector(".wrongAnswers");
let score = 0;
let wrongAnswers = 0;
// Rest Countries
function newQuestion() {
fetch("https://restcountries.eu/rest/v2/all")
.then(response => response.json())
.then(data => initialize(data))
.catch(error => console.log("Error:", error));
function initialize(countriesData) {
// Define countries
countries = countriesData;
// Create an empty string where you add your option value in at random as a string
let options = "";
countries.forEach(country => options += `<option value="${country.alpha3Code}">${country.name}</option>`);
countriesList.innerHTML = options;
// Random index of one instance of the API call
countriesList.selectedIndex = Math.floor(Math.random() * countriesList.length);
// Set or return the index of the selected value
// for display card
displayCountryInfo(countriesList[countriesList.selectedIndex].value);
// displayCountryInfo(countriesList.value);
}
function displayCountryInfo(countryByAlpha3Code) {
let addQuestions = document.querySelector(".question");
const countryData = countries.find(country => country.alpha3Code === countryByAlpha3Code);
selectedCountry = countryData.name;
document.querySelector("#flag-container img").src = countryData.flag;
// If the flag fails to load, display the country name
document.querySelector("#flag-container img").alt = `flag of ${countryData.name}`;
document.getElementById("country").innerHTML = countryData.name;
document.getElementById("capital").innerHTML = countryData.capital;
document.getElementById("population").innerHTML = countryData.population.toLocaleString("en-US");
document.getElementById("currencies").innerHTML = countryData.currencies.filter(c => c.name).map(c => `${c.name} (${c.code})`).join(', ');
let languages = document.getElementById("languages").innerHTML = countryData.languages.filter(l => l.name).map(l => `${l.name}`).join(', ');
document.getElementById("region").innerHTML = countryData.region;
document.getElementById("subregion").innerHTML = countryData.subregion;
document.getElementById("lat-long").innerHTML = countryData.latlng;
initMap(countryData);
addQuestions.innerHTML = `I am located in ${countryData.subregion}. There are ${countryData.languages.length} language(s) spoken here: ${languages}. My capital city is ${countryData.capital}. What's my name?`;
function multipleChoice() {
for (let i = 0; i < 7; i++) {
let $input = document.querySelector('#inputs');
$input.innerHTML = $input.innerHTML + `<input id='choice${i}' name='countries' type='radio' onchange='getValue(this)' value='${countries[i].name}'/> ${countries[i].name}`;
}
}
multipleChoice();
}
// Access Google Maps API
function initMap(country) {
// Create a variable
let myLatLng = new google.maps.LatLng(country.latlng[0], country.latlng[1]);
//object literal
//instantiate map with mapOptions object
let mapOptions = {
center: myLatLng,
zoom: 5,
disableDefaultUI: true,
mapTypeId: 'satellite',
heading: 90,
tilt: 45,
rotateControl: true,
}
let marker = new google.maps.Marker({
position: myLatLng
});
// Create map
let map = new google.maps.Map(document.getElementById("mapDiv"), mapOptions);
// Set marker
marker.setMap(map);
}
}
newQuestion();
function getValue(element) {
if (element.value === selectedCountry) {
score++;
updateScore.innerHTML = `Score: ${score}`;
newQuestion();
if (score === 10) {
gameTitle.innerHTML = "You Won!";
}
} else {
wrongAnswers++;
guesses.innerHTML = `Wrong guesses ${wrongAnswers}`
newQuestion();
if (wrongAnswers === 3) {
gameTitle.innerHTML = "Game Over!";
}
}
}
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 15px;
background: rgb(51, 45, 45);
height: 100%;
margin: 0;
padding: 0;
}
p {
padding: 0 2.5rem 2.5rem;
margin: 0;
}
h3, .score, .wrongAnswers {
text-align: center;
}
html {
font-family: 'Dosis', sans-serif;
height: 100%;
}
#mapDiv {
height: 50%;
}
#main-container {
display: none;
float: right;
width: 502px;
margin: 30px auto;
padding: 0;
}
#flag-container {
float: left;
height: 252px;
width: 502px;
background-color: rgb(19, 16, 16);
border: 10px solid rgb(32, 13, 28);
box-shadow: 2px 4px 25px rgb(27, 4, 4);
}
#flag-container img {
width: 100%;
height: 100%;
}
#quiz-container {
color: white;
background: rgb(51, 45, 45);
overflow: hidden;
}
@media screen and (max-width: 768px) {
body {
font-size: 12px;
}
#main-container {
width: 342px;
}
#flag-container {
height: 172px;
width: 50%;
}
#info-container select {
font-size: 12px; font-weight: 600;
}
}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>MapApp Quiz</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="main.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"> -->
</head>
<body>
<div id="mapDiv"><h1></h1></div>
<div id="root"></div>
<div id="flag-container">
<img src="" alt="">
</div>
<div id="main-container">
<div class="card">
<div id="info-container">
<select id="countries"></select>
<p>Country: <span id="country"></span></p>
<p>Capital: <span id="capital"></span></p>
<p>Population: <span id="population"></span></p>
<p>Currencies: <span id="currencies"></span></p>
<p>Languages: <span id="languages"></span></p>
<p>Region: <span id="region"></span></p>
<p>Subregion: <span id="subregion"></span></p>
<p>Lat/Long: <span id="lat-long"></span></p>
</div>
</div>
</div>
<div id="quiz-container">
<h3 class="gameTitle">MapApp Quiz</h3>
<h5 class="score">Score: 0</h5>
<h5 class="wrongAnswers">Wrong guesses: 0</h5>
<p class="question"></p>
<form id="inputs">
</form>
</div>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=[API_KEY]"></script>
<script src="main.js" async defer></script>
</body>
</html>
Upvotes: 2
Views: 2039
Reputation: 36349
Ok, so it's not clear to me how you're selecting the "correct" answer, but let's assume you have one country that is the answer and then the list of all countries. You could make a list of 4 random countries plus the correct country like so:
function generateAnswers(answer, allCountries) {
let wrongCountries = allCountries.filter(country => country.alpha3Code !== answer.alpha3Code);
const countOfAnswers = 5;
const positionOfCorrectAnswer = Math.floor(Math.random() * (countOfAnswers + 1));
const answers = [];
for(let i=0; i< countOfAnswers; i++) {
if (i === positionOfCorrectAnswer) {
answers.push(answer);
} else {
let randomAnswer = wrongCountries[Math.floor(Math.random() * wrongCountries.length)];
wrongCountries = wrongCountries.filter(country => country.alpha3Code !== randomAnswer.alpha3Code);
answers.push({ name: randomAnswer.name, alpha3Code: randomAnswer.alpha3Code } );
}
}
return answers;
};
Ok, so this function should return you an array of 5 countries including the right answer and 4 random wrong answers. You can call this in your code that builds the options and build the HTML from it, rather than using the full list of countries.
Upvotes: 1