Skip to content

Commit

Permalink
Merge pull request #2 from smdthiranjaya/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
smdthiranjaya authored Apr 4, 2024
2 parents 07cfd42 + 4bc261e commit d7922f9
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 48 deletions.
48 changes: 0 additions & 48 deletions index.js

This file was deleted.

21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.19.1",
"node-fetch": "^3.3.2",
Expand Down
30 changes: 30 additions & 0 deletions server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const express = require('express');
const cors = require('cors');
const { PORT } = require('./src/config');
const weatherRoutes = require('./src/routes/weatherRoutes');
const { updateWeatherDataManually } = require('./src/controllers/weatherController');
const swaggerUi = require('swagger-ui-express');
const swaggerDocs = require('./src/swaggerConfig');

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocs));

const app = express();
app.use(cors());

app.use(weatherRoutes);

app.get('/', (req, res) => {
res.send('Weather Data Fetching Service is running.');
});

setInterval(async () => {
try {
await updateWeatherDataManually();
} catch (error) {
console.error('Failed to fetch or store weather data:', error);
}
}, 300000); // 5 minutes

app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
6 changes: 6 additions & 0 deletions src/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
require('dotenv').config();

module.exports = {
PORT: process.env.PORT || 3000,
DATABASE_URL: process.env.DATABASE_URL
};
100 changes: 100 additions & 0 deletions src/controllers/weatherController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const { storeWeatherData, fetchAllWeatherData } = require('../models/weatherModel');

async function updateWeatherDataManually() {
console.log('Fetching and Storing weather data...');

// Define all cities with base information
const cities = [
{ id: 1, city: 'Colombo', lat: 6.932, lng: 79.848 },
{ id: 2, city: 'Kandy', lat: 7.296, lng: 80.636 },
{ id: 3, city: 'Galle', lat: 6.037, lng: 80.217 },
{ id: 4, city: 'Jaffna', lat: 9.669, lng: 80.007 },
{ id: 5, city: 'Trincomalee', lat: 8.571, lng: 81.234 },
{ id: 6, city: 'Vavuniya', lat: 8.751, lng: 80.497 },
{ id: 7, city: 'Anuradhapura', lat: 8.312, lng: 80.413 },
{ id: 8, city: 'Puttalam', lat: 8.036, lng: 79.828 },
{ id: 9, city: 'Polonnaruwa', lat: 7.94, lng: 81.003 },
{ id: 10, city: 'Batticaloa', lat: 7.71, lng: 81.692 },
{ id: 11, city: 'Kurunegala', lat: 7.486, lng: 80.362 },
{ id: 12, city: 'Ratnapura', lat: 6.683, lng: 80.399 },
{ id: 13, city: 'Nuwara Eliya', lat: 6.971, lng: 80.783 },
{ id: 14, city: 'Badulla', lat: 6.99, lng: 81.056 },
{ id: 15, city: 'Pottuvil', lat: 6.876, lng: 81.827 }
];


const weatherIconMapping = {
'Sunny': 'https://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0001_sunny.png',
'Partly cloudy': 'https://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0002_sunny_intervals.png',
'Cloudy': 'https://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0004_black_low_cloud.png',
'Light rain shower': 'https://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png',
'Patchy rain nearby': 'https://cdn.worldweatheronline.com/images/wsymbols01_png_64/wsymbol_0009_light_rain_showers.png'
};

const manualWeatherData = cities.map(city => {
const descriptions = Object.keys(weatherIconMapping);
const weatherDescriptions = descriptions[Math.floor(Math.random() * descriptions.length)];
const weatherIcons = weatherIconMapping[weatherDescriptions];

const temperature = Math.floor(Math.random() * 15) + 20;
const humidity = Math.floor(Math.random() * 50) + 50;
const airPressure = Math.floor(Math.random() * 6) + 1009;
const windSpeed = Math.floor(Math.random() * 15) + 5;
const isDay = true;
const observationTime = `${Math.floor(Math.random() * 12) + 1}:00 ${Math.random() > 0.5 ? 'AM' : 'PM'}`;

return {
id: city.id,
city: city.city,
lat: city.lat,
lng: city.lng,
temperature,
humidity,
airPressure,
windSpeed,
weatherDescriptions,
observationTime,
weatherIcons,
isDay
};
});

const client = await pool.connect();
try {
await client.query('BEGIN');
for (const data of manualWeatherData) {
const insertQuery = `
INSERT INTO weather_data (id, city, latitude, longitude, temperature, humidity, air_pressure, wind_speed, weather_descriptions, observation_time, weather_icons, is_day)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
ON CONFLICT (id) DO UPDATE
SET temperature = EXCLUDED.temperature,
humidity = EXCLUDED.humidity,
air_pressure = EXCLUDED.air_pressure,
wind_speed = EXCLUDED.wind_speed,
weather_descriptions = EXCLUDED.weather_descriptions,
observation_time = EXCLUDED.observation_time,
weather_icons = EXCLUDED.weather_icons,
is_day = EXCLUDED.is_day;
`;
const values = [
data.id, data.city, data.lat, data.lng, data.temperature, data.humidity,
data.airPressure, data.windSpeed, data.weatherDescriptions, data.observationTime,
data.weatherIcons, data.isDay
];
await client.query(insertQuery, values);
}
await client.query('COMMIT');
} catch (e) {
console.error('Failed to update weather data:', e);
await client.query('ROLLBACK');
} finally {
client.release();
}
}


// async function getWeather(req, res) {
// // Your route logic here
// }

module.exports = { updateWeatherDataManually };
11 changes: 11 additions & 0 deletions src/db/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { Pool } = require('pg');
const { DATABASE_URL } = require('../config');

const pool = new Pool({
connectionString: DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
});

module.exports = pool;
42 changes: 42 additions & 0 deletions src/models/weatherModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const pool = require('../db');

async function storeWeatherData(weatherData) {
console.log('Storing weather data...');
const client = await pool.connect();
try {
await client.query('BEGIN');
for (const data of weatherData) {
const insertQuery = `
INSERT INTO weather_data (id, city, latitude, longitude, temperature, humidity, air_pressure, wind_speed, weather_descriptions, observation_time, weather_icons, is_day)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
ON CONFLICT (id) DO UPDATE
SET temperature = EXCLUDED.temperature,
humidity = EXCLUDED.humidity,
air_pressure = EXCLUDED.air_pressure,
wind_speed = EXCLUDED.wind_speed,
weather_descriptions = EXCLUDED.weather_descriptions,
observation_time = EXCLUDED.observation_time,
weather_icons = EXCLUDED.weather_icons,
is_day = EXCLUDED.is_day;
`;
const values = [
data.id, data.city, data.lat, data.lng, data.temperature, data.humidity,
data.airPressure, data.windSpeed, data.weatherDescriptions, data.observationTime,
data.weatherIcons, data.isDay
];
await client.query(insertQuery, values);
}
await client.query('COMMIT');
} catch (e) {
await client.query('ROLLBACK');
throw e;
} finally {
client.release();
}
}

// async function fetchAllWeatherData() {
// // Logic to fetch all weather data from DB
// }

module.exports = { storeWeatherData };
38 changes: 38 additions & 0 deletions src/routes/weatherRoutes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const express = require('express');
const { getWeather } = require('../controllers/weatherController');
const router = express.Router();

router.get('/api/weather', getWeather);

/**
* @swagger
* /api/weather:
* get:
* summary: Retrieves weather data
* description: Fetches weather data for all cities.
* responses:
* 200:
* description: A list of weather data.
* content:
* application/json:
* schema:
* type: array
* items:
* $ref: '#/components/schemas/Weather'
* components:
* schemas:
* Weather:
* type: object
* required:
* - city
* - temperature
* properties:
* city:
* type: string
* description: The city's name
* temperature:
* type: integer
* description: The current temperature
*/

module.exports = router;
20 changes: 20 additions & 0 deletions src/swaggerConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const swaggerJsDoc = require('swagger-jsdoc');

const swaggerOptions = {
definition: {
openapi: '3.0.0',
info: {
title: 'Weather API',
version: '1.0.0',
description: 'A simple Express Weather API'
},
servers: [
{
url: 'http://localhost:3000'
}
],
},
apis: ['./src/routes/*.js'],
};

module.exports = swaggerJsDoc(swaggerOptions);

0 comments on commit d7922f9

Please sign in to comment.