From feba72cd429e99a4c349622c810f9d6383446de5 Mon Sep 17 00:00:00 2001 From: eoneoff Date: Tue, 17 Dec 2019 22:52:06 +0200 Subject: [PATCH 1/6] weather-api --- submissions/eoneoff/weather-api/getWeather.js | 48 +++++++++++ submissions/eoneoff/weather-api/main.js | 22 +++++ .../eoneoff/weather-api/manageCities.js | 68 +++++++++++++++ .../eoneoff/weather-api/showWeather.js | 67 +++++++++++++++ .../eoneoff/weather-api/weatherIcons.js | 85 +++++++++++++++++++ submissions/eoneoff/weather-api/wrongCity.js | 32 +++++++ 6 files changed, 322 insertions(+) create mode 100644 submissions/eoneoff/weather-api/getWeather.js create mode 100644 submissions/eoneoff/weather-api/main.js create mode 100644 submissions/eoneoff/weather-api/manageCities.js create mode 100644 submissions/eoneoff/weather-api/showWeather.js create mode 100644 submissions/eoneoff/weather-api/weatherIcons.js create mode 100644 submissions/eoneoff/weather-api/wrongCity.js diff --git a/submissions/eoneoff/weather-api/getWeather.js b/submissions/eoneoff/weather-api/getWeather.js new file mode 100644 index 0000000..3e4526d --- /dev/null +++ b/submissions/eoneoff/weather-api/getWeather.js @@ -0,0 +1,48 @@ +'use strict'; + +const axios = require('axios'); + +const weather = axios.create({ + baseURL: 'http://api.openweathermap.org/data/2.5/', + params: { + APPID: 'c4ad7974f3977f8f388a60b5c0267caa' + } +}); + +module.exports.getWeather = async function (mode, location, units) { + const data = (await weather.get(mode, { + params: { + q: location, + units: units + } + })).data; + const wData = []; + if (mode === 'weather') { + const dData = makeWeatherData(data); + dData.city = data.name; + wData.push(dData); + } else { + for (const day of data.list) { + const dData = makeWeatherData(day); + dData.city = data.city.name; + wData.push(dData); + } + } + return wData; +}; + +function makeWeatherData (data) { + const day = { + icon: '_' + data.weather[0].icon, + date: new Date(data.dt * 1000), + description: data.weather[0].description, + temp: data.main.temp, + maxTemp: data.main.temp_max, + minTemp: data.main.temp_min, + wind: { + deg: data.wind.deg, + speed: data.wind.speed + } + }; + return day; +} diff --git a/submissions/eoneoff/weather-api/main.js b/submissions/eoneoff/weather-api/main.js new file mode 100644 index 0000000..9ada881 --- /dev/null +++ b/submissions/eoneoff/weather-api/main.js @@ -0,0 +1,22 @@ +'use strict'; + +const { showWeather } = require('./showWeather'); + +const argv = require('yargs') + .option('range', { + alias: 'r', + type: 'string' + }) + .option('location', { + alias: 'l', + type: 'string' + }) + .option('units', { + alias: 'u', + type: 'string' + }).argv; + +const mode = argv.range === 'week' ? 'forecast' : 'weather'; +const units = argv.units === 'farenheit' ? 'imperial' : 'metric'; + +showWeather(mode, argv.location || '', units); diff --git a/submissions/eoneoff/weather-api/manageCities.js b/submissions/eoneoff/weather-api/manageCities.js new file mode 100644 index 0000000..1ab0033 --- /dev/null +++ b/submissions/eoneoff/weather-api/manageCities.js @@ -0,0 +1,68 @@ +'use strict'; + +const fs = require('fs'); + +function saveRecent (city) { + const recent = readRecent(); + if (recent.indexOf(city) === -1) { + recent.unshift(city); + if (recent.lenght > 9) recent.pop(); + writeRecent(recent); + } +} + +function saveFavorite (city) { + const favorite = readFavorite(); + const exists = favorite.find(c => c.name === city); + if (exists) exists.count++; + else { + favorite.push({ + name: city, + count: 1 + }); + } + writeFavorite(favorite.sort((a, b) => a.count - b.count).reverse().slice(0, 10)); +} + +function readFavorite () { + if (fs.existsSync('favorite.csv')) { + const output = fs.readFileSync('favorite.csv').toString() + .split('\n') + .map(c => { + const cData = c.split(';'); + return { + name: cData[0], + count: cData[1] + }; + }); + return output; + } + + return []; +} + +function writeFavorite (favorite) { + fs.writeFile('favorite.csv', favorite.map(c => { + return `${c.name};${c.count}`; + }).join('\n'), () => {}); +} + +function readRecent () { + if (fs.existsSync('recent.csv')) { + return fs.readFileSync('recent.csv').toString().split('\n'); + } + return []; +} + +function writeRecent (recent) { + fs.writeFile('recent.csv', recent.join('\n'), () => {}); +} + +module.exports.saveCities = (city) => { + saveRecent(city); + saveFavorite(city); +}; + +module.exports.getRecent = readRecent; + +module.exports.getFavourite = readFavorite; diff --git a/submissions/eoneoff/weather-api/showWeather.js b/submissions/eoneoff/weather-api/showWeather.js new file mode 100644 index 0000000..4c158b1 --- /dev/null +++ b/submissions/eoneoff/weather-api/showWeather.js @@ -0,0 +1,67 @@ +'use strict'; + +const { getWeather } = require('./getWeather'); +const { icons } = require('./weatherIcons'); +const { saveCities } = require('./manageCities'); +const { wrongCity } = require('./wrongCity'); +const Table = require('cli-table3'); +const { cyan: c } = require('chalk'); + +function showBlocks (data, tUnit, wUnit) { + for (const day of data) { + dayBlock(day, tUnit, wUnit); + } +} + +function dayBlock (data, tUnit, wUnit) { + const block = new Table({ + chars: { + 'top-mid': '─', + 'bottom-mid': '─', + 'left-mid': '', + mid: '', + 'mid-mid': '', + 'right-mid': '', + middle: ' ' + }, + colWidths: [17, 40] + }); + block.push([icons[data.icon], weatherData(data, tUnit, wUnit)]); + process.stdout.write(block.toString() + '\n'); +} + +function weatherData (data, tUnit, wUnit) { + return `\n${c('Location:')} ${data.city}\n` + + `${c('Date:')} ${data.date.toDateString()}\n` + + `${c('Time')} ${data.date.toLocaleTimeString()}\n` + + `${data.description}\n` + + `${c('Temperature:')} ${data.temp}${tUnit}\n` + + `${c('Maximum temperature:')} ${data.maxTemp}${tUnit}\n` + + `${c('Minimum temperature:')} ${data.minTemp}${tUnit}\n` + + `${c('Wind:')} ${windDirection(data.wind.deg)} ${data.wind.speed}${wUnit}\n`; +} + +function windDirection (wind) { + if (wind > 338 || wind < 22) return 'N'; + if (wind < 67) return 'NE'; + if (wind < 112) return 'E'; + if (wind < 157) return 'SE'; + if (wind < 202) return 'S'; + if (wind < 247) return 'SW'; + if (wind < 292) return 'W'; + return 'NW'; +} + +module.exports.showWeather = function showWeather (mode, location, units) { + getWeather(mode, location, units).then(data => { + showBlocks(data, + units === 'imperial' ? 'F°' : 'C°', + units === 'imperial' ? 'mph' : 'm/s', + data.name); + saveCities(location); + }).catch(error => { + if ((error.response.data || {}).message === 'city not found' || (error.response.data || {}).message === 'Nothing to geocode') { + wrongCity(location).then(c => showWeather(mode, c, units)); + } else throw (error); + }); +}; diff --git a/submissions/eoneoff/weather-api/weatherIcons.js b/submissions/eoneoff/weather-api/weatherIcons.js new file mode 100644 index 0000000..0994fbb --- /dev/null +++ b/submissions/eoneoff/weather-api/weatherIcons.js @@ -0,0 +1,85 @@ +const { yellow: y, cyan: c, gray: g } = require('chalk'); + +const icons = { + _01d: y(` + OOO + OOOOO +(OOOOO) + OOOOO + OOO`), + _01n: ` + OOO + OOOOO +(OOOOO) + OOOOO + OOO`, + _02d: ` + ${c('@@@')} ${y('OOO')} + ${c('@ @@@')}${y('OOO')} + ${c('@@ @@@')}${y('OO)')} + ${c(`@@@ @@@@@@ + @@@@@@@@@@@@@@`)}`, + _02n: ` + ${c('@@@')} OOO + ${c('@ @@@')}OOO + ${c('@@ @@@')}OO) + ${c(`@@@ @@@@@@ + @@@@@@@@@@@@@@`)}`, + _03d: c(` + @@@ + @ @@@ + @@ @@@ + @@@ @@@@@@ +@@@@@@@@@@@@@@`), + _04d: ` + ${c('@@@')}${g('##')} + ${c(' @ @@@')}${g('##')} + ${c('@@ @@@')}${g('##')} + ${c('@@@ @@@@@')}${g('###')} + ${c('@@@@@@@@@@@@@@')}`, + _09d: ` + ${c('@@@')}${g('##')} + ${c('@ @@@')}${g('##')} + ${c('@@ @@@')}${g('##')} + ${c('@@@@@@@@@@@@')} + ${g(',\',\',\',\',\',\',')}`, + _10d: ` + ${c('@@@')} ${y('OOO')} + ${c('@@ @@@')}${y('OOO')} + ${c('@@@ @@@@')}${y('O)')} + ${c('@@@@@@@@@@@@')} + ${g(',\',\',\',\',\',\'')}`, + _10n: ` + ${c('@@@')} OOO + ${c('@@ @@@')}OOO + ${c('@@@ @@@@')}O) +${c('@@@@@@@@@@@@')} +${g(',\',\',\',\',\',\'')}`, + _11d: ` + ${c('@@@')}${g('##')} + ${c('@@@')}${y('/')}${c('@@')}${g('##')} +${c('@@@')}${y('/_')}${c('@@@')}${g('##')} + ${y(`/ + /`)}`, + _13d: ` + * +***** + *** +***** + *`, + _50d: g(` + — + --—— + —--— + —---—-- + —--—`) +}; + +icons._03n = icons._03d; +icons._04n = icons._04d; +icons._09n = icons._09d; +icons._11n = icons._11d; +icons._13n = icons._13d; +icons._50n = icons._50d; + +module.exports.icons = icons; diff --git a/submissions/eoneoff/weather-api/wrongCity.js b/submissions/eoneoff/weather-api/wrongCity.js new file mode 100644 index 0000000..dede840 --- /dev/null +++ b/submissions/eoneoff/weather-api/wrongCity.js @@ -0,0 +1,32 @@ +const rl = require('readline-sync'); +const { getRecent, getFavourite } = require('./manageCities'); + +function selectRecent () { + const recent = getRecent(); + const option = rl.keyInSelect(recent, 'Select'); + return option === -1 ? '' : recent[option]; +} + +function selectFavourite () { + const favourite = getFavourite().map(city => city.name); + const option = rl.keyInSelect(favourite, 'Select'); + return option === -1 ? '' : favourite[option]; +} + +module.exports.wrongCity = async function (name) { + const options = ['Select city form recent', 'Select city from favourite', 'Enter city']; + process.stdout.write(name ? `There is no weather data for the city with the name ${name}\n` + : 'There is no city name provided\n'); + process.stdout.write('Would you like to'); + const option = rl.keyInSelect(options, 'Select'); + switch (option) { + case 0: + return selectRecent(); + case 1: + return selectFavourite(); + case 2: + return rl.question('Enter city name: '); + case -1: + process.exit(0); + } +}; From 1e241b814e9ba97b303ff965aef6ca9b223a1631 Mon Sep 17 00:00:00 2001 From: eoneoff Date: Wed, 18 Dec 2019 20:26:50 +0200 Subject: [PATCH 2/6] added dependencies --- submissions/eoneoff/package.json | 22 ++++++++++++++++++++ submissions/eoneoff/weather-api/package.json | 21 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 submissions/eoneoff/package.json create mode 100644 submissions/eoneoff/weather-api/package.json diff --git a/submissions/eoneoff/package.json b/submissions/eoneoff/package.json new file mode 100644 index 0000000..a01a899 --- /dev/null +++ b/submissions/eoneoff/package.json @@ -0,0 +1,22 @@ +{ + "name": "eoneoff", + "version": "1.0.0", + "description": "kottans nodejs", + "main": "''", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/eoneoff/nodejs-2019-homeworks.git" + }, + "author": "eoneoff", + "license": "ISC", + "bugs": { + "url": "https://github.com/eoneoff/nodejs-2019-homeworks/issues" + }, + "homepage": "https://github.com/eoneoff/nodejs-2019-homeworks#readme", + "devDependencies": { + "semistandard": "^14.2.0" + } +} diff --git a/submissions/eoneoff/weather-api/package.json b/submissions/eoneoff/weather-api/package.json new file mode 100644 index 0000000..fab2ad0 --- /dev/null +++ b/submissions/eoneoff/weather-api/package.json @@ -0,0 +1,21 @@ +{ + "name": "weather-api", + "version": "1.0.0", + "description": "", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/eoneoff/nodejs-2019-homeworks/tree/master/submissions/eoneoff/weather-api" + }, + "author": "eoneoff", + "license": "ISC", + "dependencies": { + "axios": "^0.19.0", + "chalk": "^3.0.0", + "cli-table": "^0.3.1", + "readline-sync": "^1.4.10" + } +} From fc207901c5c87d5408b327eeea82ed3032a386e6 Mon Sep 17 00:00:00 2001 From: eoneoff Date: Sun, 22 Dec 2019 11:02:44 +0200 Subject: [PATCH 3/6] corrections applied --- submissions/eoneoff/weather-api/getWeather.js | 11 ++---- .../eoneoff/weather-api/manageCities.js | 38 ++++++++----------- .../eoneoff/weather-api/showWeather.js | 7 ++-- 3 files changed, 24 insertions(+), 32 deletions(-) diff --git a/submissions/eoneoff/weather-api/getWeather.js b/submissions/eoneoff/weather-api/getWeather.js index 3e4526d..d012294 100644 --- a/submissions/eoneoff/weather-api/getWeather.js +++ b/submissions/eoneoff/weather-api/getWeather.js @@ -18,22 +18,19 @@ module.exports.getWeather = async function (mode, location, units) { })).data; const wData = []; if (mode === 'weather') { - const dData = makeWeatherData(data); - dData.city = data.name; - wData.push(dData); + wData.push(makeWeatherData(data, data.name)); } else { for (const day of data.list) { - const dData = makeWeatherData(day); - dData.city = data.city.name; - wData.push(dData); + wData.push(makeWeatherData(day, data.city.name)); } } return wData; }; -function makeWeatherData (data) { +function makeWeatherData (data, name) { const day = { icon: '_' + data.weather[0].icon, + city = name, date: new Date(data.dt * 1000), description: data.weather[0].description, temp: data.main.temp, diff --git a/submissions/eoneoff/weather-api/manageCities.js b/submissions/eoneoff/weather-api/manageCities.js index 1ab0033..612bbe6 100644 --- a/submissions/eoneoff/weather-api/manageCities.js +++ b/submissions/eoneoff/weather-api/manageCities.js @@ -4,11 +4,9 @@ const fs = require('fs'); function saveRecent (city) { const recent = readRecent(); - if (recent.indexOf(city) === -1) { - recent.unshift(city); - if (recent.lenght > 9) recent.pop(); - writeRecent(recent); - } + if(recent.includes(city)) return; + recent.unshift(city); + writeRecent(recent.slice(0, 10)); } function saveFavorite (city) { @@ -25,26 +23,22 @@ function saveFavorite (city) { } function readFavorite () { - if (fs.existsSync('favorite.csv')) { - const output = fs.readFileSync('favorite.csv').toString() - .split('\n') - .map(c => { - const cData = c.split(';'); - return { - name: cData[0], - count: cData[1] - }; - }); - return output; - } - - return []; + if (!fs.existsSync('favorite.csv')) return []; + + const output = fs.readFileSync('favorite.csv').toString() + .split('\n') + .map(c => { + const cData = c.split(';'); + return { + name: cData[0], + count: cData[1] + }; + }); + return output; } function writeFavorite (favorite) { - fs.writeFile('favorite.csv', favorite.map(c => { - return `${c.name};${c.count}`; - }).join('\n'), () => {}); + fs.writeFile('favorite.csv', favorite.map(c => `${c.name};${c.count}`).join('\n'), () => {}); } function readRecent () { diff --git a/submissions/eoneoff/weather-api/showWeather.js b/submissions/eoneoff/weather-api/showWeather.js index 4c158b1..bb88414 100644 --- a/submissions/eoneoff/weather-api/showWeather.js +++ b/submissions/eoneoff/weather-api/showWeather.js @@ -19,10 +19,10 @@ function dayBlock (data, tUnit, wUnit) { 'top-mid': '─', 'bottom-mid': '─', 'left-mid': '', - mid: '', + 'mid': '', 'mid-mid': '', 'right-mid': '', - middle: ' ' + 'middle': ' ' }, colWidths: [17, 40] }); @@ -60,7 +60,8 @@ module.exports.showWeather = function showWeather (mode, location, units) { data.name); saveCities(location); }).catch(error => { - if ((error.response.data || {}).message === 'city not found' || (error.response.data || {}).message === 'Nothing to geocode') { + const message = (error.response.data || {}).message; + if (message === 'city not found' || message === 'Nothing to geocode') { wrongCity(location).then(c => showWeather(mode, c, units)); } else throw (error); }); From cbc97efca20b7efbac354376919ecef6a3d6872d Mon Sep 17 00:00:00 2001 From: eoneoff Date: Sun, 22 Dec 2019 12:46:29 +0200 Subject: [PATCH 4/6] makeWeatherData error corrected --- submissions/eoneoff/weather-api/getWeather.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submissions/eoneoff/weather-api/getWeather.js b/submissions/eoneoff/weather-api/getWeather.js index d012294..654d57b 100644 --- a/submissions/eoneoff/weather-api/getWeather.js +++ b/submissions/eoneoff/weather-api/getWeather.js @@ -30,7 +30,7 @@ module.exports.getWeather = async function (mode, location, units) { function makeWeatherData (data, name) { const day = { icon: '_' + data.weather[0].icon, - city = name, + city: name, date: new Date(data.dt * 1000), description: data.weather[0].description, temp: data.main.temp, From 4ded367427b471464cef630f9d1650b2b4892716 Mon Sep 17 00:00:00 2001 From: eoneoff Date: Mon, 23 Dec 2019 18:24:59 +0200 Subject: [PATCH 5/6] linter errors corrected --- submissions/eoneoff/weather-api/manageCities.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/submissions/eoneoff/weather-api/manageCities.js b/submissions/eoneoff/weather-api/manageCities.js index 612bbe6..0d39687 100644 --- a/submissions/eoneoff/weather-api/manageCities.js +++ b/submissions/eoneoff/weather-api/manageCities.js @@ -4,7 +4,7 @@ const fs = require('fs'); function saveRecent (city) { const recent = readRecent(); - if(recent.includes(city)) return; + if (recent.includes(city)) return; recent.unshift(city); writeRecent(recent.slice(0, 10)); } @@ -24,7 +24,7 @@ function saveFavorite (city) { function readFavorite () { if (!fs.existsSync('favorite.csv')) return []; - + const output = fs.readFileSync('favorite.csv').toString() .split('\n') .map(c => { From ff764dcf5491ed18bd5a6cb2682403971433a2b2 Mon Sep 17 00:00:00 2001 From: eoneoff Date: Mon, 23 Dec 2019 19:05:28 +0200 Subject: [PATCH 6/6] fixed linter problems --- submissions/eoneoff/weather-api/showWeather.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/submissions/eoneoff/weather-api/showWeather.js b/submissions/eoneoff/weather-api/showWeather.js index bb88414..0b186e3 100644 --- a/submissions/eoneoff/weather-api/showWeather.js +++ b/submissions/eoneoff/weather-api/showWeather.js @@ -19,10 +19,10 @@ function dayBlock (data, tUnit, wUnit) { 'top-mid': '─', 'bottom-mid': '─', 'left-mid': '', - 'mid': '', + mid: '', 'mid-mid': '', 'right-mid': '', - 'middle': ' ' + middle: ' ' }, colWidths: [17, 40] });