require('dotenv').config(); const debug = require('debug')('soundbirder:api:quizz'); const debugResponses = require('debug')('soundbirder:api:responses'); const cache = require('./cache'); const eBird = require('@unclesamulus/ebird-api')(process.env.EBIRD_API_KEY); const XenoCanto = require('@unclesamulus/xeno-canto-api'); const { choices, choice } = require('../utils/choices'); const { getRegion } = require('./region'); async function generateQuizz(coordinates, locale, size) { const quizz = {} try { const speciesSelection = await getSpeciesSelection(coordinates, size); debugResponses(`Species selection: ${speciesSelection}`); const speciesSelectionLocalized = await getLocalizedNames(speciesSelection, locale); debugResponses('Localized species selection:', speciesSelectionLocalized); quizz.species = speciesSelectionLocalized; debug("Got species selection", quizz.species); let answer; do { answer = choice(speciesSelectionLocalized); quizz.answer = answer; quizz.audio = await getAudio(answer.sciName); if (quizz.audio == undefined) { debug("No audio found for species", answer.sciName); debug("Trying again..."); } } while (quizz.audio == undefined); debug("Got answer", answer); debug("Got audio", quizz.audio); } catch (error) { debug("Error raised while generating quizz"); console.error(error); } return quizz; } async function getSpeciesSelection(coordinates, number) { const { lat, lng } = coordinates; const region = await getRegion(lat, lng); // const regionCode = await getRegionCode(region); const regionCode = region.country_code; const speciesList = await getSpeciesList(regionCode); const speciesSelection = choices(speciesList, number); debug("Species proposals:", speciesSelection) return speciesSelection; } async function getLocalizedNames(speciesCodes, locale) { let allNames = []; for (let i = 0; i < speciesCodes.length; i++) { const code = speciesCodes[i]; let flag = false; try { names = await cache.getCached(`${code}-${locale}`); if (names) { allNames.push(names); flag = true; } } catch (error) { console.error(error); } if (!flag) { try { const names = { speciesCode, sciName, comName } = await getLocalizedName(code, locale); cache.cacheResponse(`${code}-${locale}`, names); allNames.push(names); } catch (error) { console.error(error); } } } return allNames; } function getLocalizedName(speciesCode, locale) { return eBird.ref.taxonomy.ebird({ fmt: 'json', locale: locale, species: speciesCode }).then( response => { const names = response[0]; debug("Got localized species names"); debugResponses(names); return names; } ).catch(error => { throw error; }); } async function getSpeciesList(regionCode) { const cached = await cache.getCached(`spplist-${regionCode}`); if (cached) { return cached; } else { return eBird.product.spplist.in(regionCode)() .then(species => { cache.cacheResponse(`spplist-${regionCode}`, species); return species; }) .catch(error => { throw error; }); } } function getAudio(speciesScientificName) { return XenoCanto.search({ name: speciesScientificName, quality: 'A' }).then(response => { debugResponses(response); const { recordings } = response; const randomRecord = choice(recordings); const audio = randomRecord.file; return audio; }).catch(error => { throw error; }); } module.exports = { generateQuizz }