-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
weather-api #35
base: master
Are you sure you want to change the base?
weather-api #35
Changes from 1 commit
feba72c
1e241b8
fc20790
cbc97ef
4ded367
ff764dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); |
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,68 @@ | ||||||||||||||||||
'use strict'; | ||||||||||||||||||
|
||||||||||||||||||
const fs = require('fs'); | ||||||||||||||||||
|
||||||||||||||||||
function saveRecent (city) { | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can remove nested in this function, if by using negative check and then return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I can't see how. I need to remove the last record from recent if there are more then 9 records and save the changes anyway. If I return the saving will be skipped. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I may be writing not-working code, but if it works, then its solution would be better
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I have done. One thing: not Actually I'm not sure, that it is correct to do so, because thus we make code somewhat shorter but, in my opinion less readable. This can make some sense in browser js where shorter code means less traffic, but in server node.js code it makes no sense. IMHO. But there is another problem. Semistandard finds an error in my code, but the error message encoding is a mess and I can not get where the error is. The semistandard extension for my VS Code shows no linter errors. |
||||||||||||||||||
const recent = readRecent(); | ||||||||||||||||||
if (recent.indexOf(city) === -1) { | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use |
||||||||||||||||||
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')) { | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can remove nested if by using negative check and then 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; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
return []; | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
function writeFavorite (favorite) { | ||||||||||||||||||
fs.writeFile('favorite.csv', favorite.map(c => { | ||||||||||||||||||
return `${c.name};${c.count}`; | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||
}).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; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better if you write |
||
wrongCity(location).then(c => showWeather(mode, c, units)); | ||
} else throw (error); | ||
}); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to create a "processingData" function and just call it in both situations