We will be creating our very own weather forecast application. We will be covering a lot of topics, but no need to fully grasp everything. Most of the topics here will be revisited again in other subjects such as ITE222, ITE120 , ITE220, ITE343
- Your main job is to modify the file
frontend/code.jsandfrontend/index.htmlto match the requirements below - (If you can) Decorate your website so it looks better - we will be showing each group's website at the end
- You can see the current website by using Live Server VSCode extension
- Open
frontend/index.html, then right click anywhere on the editor and choose "Open with Live Server"
- Open
-
Your main job is to modify
backend/index.jsto aggregate the data retrieved from WeatherAPI.com and send it to the frontend -
You can test the program by running following commands in the terminal
cd backendnpm i(only for the first time you're running the program)npm run start- You should be able to access the application by typing
http://localhost:3000/getForecastin your browser - Notice that there are some fields that contain invalid data (Like fields with value of
null,0, or"")- These values need to be aggregated and calculated in the backend first before sending to frontend to display
// Before { "city": "Bangkok", "temperature": 34, "condition": "Partly cloudy", "chanceOfRain": 0, "textColor": "black", "moistLevel": 0, "moonPhase": "Waning Crescent", "averageTemp": 0, "maxTemp": null, "minTemp": null, "maxUVIndex": 0, "maxUVTime": "" } // After { "city": "Bangkok", "temperature": 34, "condition": "Partly cloudy", "chanceOfRain": 0, "textColor": "red", "moistLevel": 4.7, "moonPhase": "Waning Crescent", "averageTemp": 29.754166666666666, "maxTemp": 34, "minTemp": 27.1, "maxUVIndex": 8, "maxUVTime": "2023-12-11 10:00" }
- Add logic for moon phrase emoji when moon phrase change
- Add logic for water drop emoji when moisture level change
- Update
getForecast()function after backend team finished their task
- You are free to make changes to the HTML/CSS as you prefer. However, the following data should be displayed on your website
- City Name
- Temperature (With the specified text-color)
- Chance of Rain
- Moist Level (Displayed as emojis)
- Moon Phase (Displayed as emojis)
- averageTemp
- maxTemp
- minTemp
- maxUVIndex
- maxUVTime
- Warning: Make sure that your HTML Element IDs (
cityForm, city, result) stay the same - Hint: Please use tailwind CSS for styling - the document can be found here
// just so you guys have some idea
if (forecastData.moonPhase === "Syntax Moon") {
moonPhaseEmojis = π©
}-
What this code should do:
- The code should assigns a specific moon phase emoji to the variable
moonPhaseEmojisbased on the value offorecastData.moonPhase. - Each moon phase has a corresponding emoji that visually represents it.
- The code should assigns a specific moon phase emoji to the variable
-
Initializing the Variable:
moonPhaseEmojisis initialized as an empty string. This variable will later hold the emoji that corresponds to the current moon phase.
-
Conditional Statements (if-else):
- The code uses a series of
if-elsestatements to check the value offorecastData.moonPhase. - Each condition (
iforelse if) checks for a specific moon phase (e.g., "New Moon", "Waxing Crescent"). - When a condition is met,
moonPhaseEmojisis set to the emoji representing that phase. - Hint: you can use both 'if' and 'switch' to do this, entirely up to you :3
- The code uses a series of
-
Moon Phase Emojis:
forecastData.moonPhasewill have the data of moon phrase (e.g., "New Moon", "Waxing Crescent")- The emoji display should change according to each moon phrase.
- Use π for "New Moon"
- Use π for "Waxing Crescent"
- Use π for "First Quarter"
- Use π for "Waxing Gibbous"
- Use π for "Full Moon"
- Use π for "Waning Gibbous"
- Use π for "Last Quarter"
- Use π for "Waning Crescent"
-
Tips:
- Understanding Conditional Logic: Understand how each
if-elsecondition works. What happens if the moon phase doesn't match any of the listed conditions?
- Understanding Conditional Logic: Understand how each
-
Hint: number of iteration can come from a variable called
forecastData.moistLevel// some hint for you guys - this is a combination between for loops, and string concatenation for (let i = 0; i < MOIST_LEVEL_VARIABLE; i++) { moistLevelEmojis = moistLevelEmojis + "π©"; }
-
What this code should do:
- The code should create a string of water drop emojis (π§) that visually represents a moisture level.
- The number of emojis appended corresponds to a value indicated by
forecastData.moistLevel.
-
Initializing the Variable:
moistLevelEmojisis initialized as an empty string. This variable will store the concatenated string of water drop emojis.
-
Understanding the Loop:
- A
for loopis used to repeat a block of code a number of times equal toforecastData.moistLevel. forecastData.moistLevelis expected to be a numeric value that indicates the moisture level.
- A
-
Appending Emojis:
- In each iteration of the loop, a water drop emoji (π§) is appended to
moistLevelEmojis. - The concatenation is done using the
+=operator, which adds the emoji to the end of the existing string.
- In each iteration of the loop, a water drop emoji (π§) is appended to
-
Tips:
- Understanding the Loop Mechanism: First, ensure you understand how the
for loopworks. Try tracing the loop with a small value offorecastData.moistLevel.
- Understanding the Loop Mechanism: First, ensure you understand how the
Replace the content inside function getForecast() with the code below after the backend team has finished:
try {
// Perform a fetch request to the specified URL, passing the city name as a query parameter
const response = await fetch(
`http://localhost:3000/getForecast?cityName=${cityName}`
);
// Parse the JSON response from the server
const data = await response.json();
// Return the parsed data
return data;
} catch (error) {
// Log any errors encountered during the fetch operation
console.error("Error fetching forecast:", error);
// Return null to indicate an unsuccessful operation
return null;
}- Send the text color to the frontend to display
- Calculate the moisture level and send to the frontend
- Calculate average, max, and min temperature
- Find the maximum UV index from a set of data along with the time it occurs
- Send a HTTP request to OpenWeather API to retrieve forecast data
- Convert the retrieved data into JSON format ready to be used in our program
- Assuming the JSON is as shown below. You can access each elements in your code via
data.<field-you-want-to-access>. - For example:
data.location.namewill return"Bangkok"anddata.current.temp_cwill return34.0
"location": {
"name": "Bangkok",
"region": "Krung Thep",
"country": "Thailand",
"lat": 13.75,
"lon": 100.52,
"tz_id": "Asia/Bangkok",
"localtime_epoch": 1702276925,
"localtime": "2023-12-11 13:42"
},
"current": {
"last_updated_epoch": 1702276200,
"last_updated": "2023-12-11 13:30",
"temp_c": 34.0,
"temp_f": 93.2,
"is_day": 1,
.../// and more-
If
data.current.temp_cis less than 0 - cyan -
If
data.current.temp_cis less than 15 - blue -
If
data.current.temp_cis less than 30 - orange -
Anything hotter than this can be displayed as red
if (data.current.temp_c < 999) { textColor = "purple"; }
- You can do so by dividing a variable
data.current.humidityby 10
-
Variables:
forecastDayis a variable that represents the first day in the forecast arrayhoursis an array containing weather data for in each hour (so there will be 24 elements in the array representing 24 hours)sumTempis initialized to0. This variable will hold the sum of all temperature readings.maxTempis initialized to-Infinity. This is a common technique to ensure any temperature will be higher than this initial value.minTempis initialized toInfinityfor the opposite reason; any temperature will be lower than this initial value.averageTempis a variable to hold the value of the average temperature after you have calculated it
-
Steps:
- Use
for loopto iterate over each hour in thehoursarray.hours[i].temp_cgives you the current temperature (in Celsius) for that specific hour.
- Finding the total sum of temperature
- Each iteration, add the value of current temperature(
hours[i].temp_c) tosumTemp. You can use+=operator to do it.
- Each iteration, add the value of current temperature(
- Finding the maximum and minimum temperature
- Each iteration, if the current temperature is greater than
maxTemp,maxTempis updated to this new value. - Similarly, if the current temperature is less than
minTemp,minTempis updated.
- Each iteration, if the current temperature is greater than
- Calculate the average temperature
- After the loop, divide
sumTempby the length of thehoursarray.
- After the loop, divide
for (let i = 0; i < hours.length; i++) { const currentTemperature = hours[i].temp_c; // add current temperature to sumTemp // if current temperature is greater than maxTemp, update value of maxTemp to current temperature // if current temperature is less than mainTemp, update value minTemp to the current temperature } // find average temperature
- Use
-
Variables:
maxUVIndexis initialized to 0. This will store the highest UV index found in the data.maxUVTimeis initialized to an empty string. This will later store the time at which the maximum UV index occurs.
-
Steps:
-
Use
for loopto iterate over thehoursarray, which contains hourly weather data.hours[i].uvgives you the UV index for that specific hour.hours[i].timegives you the datetime data (e.g.2023-12-11 12:00) for that specific hour.
-
Inside the loop, compares the current UV index (
hours[i].uv) withmaxUVIndex.- If the current UV index is greater than
maxUVIndex- update
maxUVIndexwith the current UV index - update
maxUVTimewith the corresponding time.
- update
- If the current UV index is greater than
-



