The contract only maps a subset of OpenWeatherMap condition codes to the contract's weather states, potentially resulting in inaccurate weather representation for certain conditions.
The GetWeather.js file implements a limited mapping of OpenWeatherMap condition codes to the contract's weather states:
This mapping doesn't account for many weather conditions that OpenWeatherMap can report, such as:
const Functions = {
makeHttpRequest: async (params) => {
if (params.url.includes("geo/1.0/zip")) {
return {
data: {
lat: 40.7128,
lon: -74.0060
}
};
} else if (params.url.includes("data/2.5/weather")) {
return {
data: {
weather: [
{
id: mockWeatherId,
main: mockWeatherMain,
description: mockWeatherDescription
}
],
main: {
temp: 20
}
}
};
}
}
};
const getWeather = (args, secrets) => {
return new Promise(async (resolve) => {
try {
const geoCodingRequest = await Functions.makeHttpRequest({
url: "http://api.openweathermap.org/geo/1.0/zip",
method: "GET",
params: { zip: `${args[0]},${args[1]}`, appid: secrets.apiKey }
});
const weatherRequest = await Functions.makeHttpRequest({
url: "https://api.openweathermap.org/data/2.5/weather",
method: "GET",
params: {
lat: geoCodingRequest.data.lat,
lon: geoCodingRequest.data.lon,
appid: secrets.apiKey
}
});
const weather_id = weatherRequest.data.weather[0].id;
const weather_id_x = Math.floor(weather_id / 100);
let weather_enum;
if (weather_id_x === 2) weather_enum = 3;
else if (weather_id_x === 3 || weather_id_x === 5) weather_enum = 2;
else if (weather_id_x === 6) weather_enum = 5;
else if (weather_id === 800) weather_enum = 0;
else if (weather_id_x === 8) weather_enum = 1;
else weather_enum = 4;
resolve([weather_enum, Math.round(weatherRequest.data.main.temp)]);
} catch (error) {
resolve([0, 0]);
}
});
};
async function runTests() {
const args = ["10001", "US"];
const secrets = { apiKey: "mock_api_key" };
console.log("Testing Limited Weather State Mapping Issues:");
console.log("\nTest Case 1: Weather ID 801 (Few clouds)");
mockWeatherId = 801;
mockWeatherMain = "Clouds";
mockWeatherDescription = "few clouds";
const result1 = await getWeather(args, secrets);
console.log(`Weather ID: ${mockWeatherId}, Description: ${mockWeatherDescription}`);
console.log(`Mapped to enum: ${result1[0]} (${getWeatherName(result1[0])})`);
console.log(`Issue: All cloud conditions (few clouds, scattered clouds, broken clouds, overcast) are mapped to the same CLOUDY state, losing detail`);
console.log("\nTest Case 2: Weather ID 511 (Freezing rain)");
mockWeatherId = 511;
mockWeatherMain = "Rain";
mockWeatherDescription = "freezing rain";
const result2 = await getWeather(args, secrets);
console.log(`Weather ID: ${mockWeatherId}, Description: ${mockWeatherDescription}`);
console.log(`Mapped to enum: ${result2[0]} (${getWeatherName(result2[0])})`);
console.log(`Issue: Freezing rain is mapped to RAINY, but could be better represented as a mix of RAINY and SNOW`);
console.log("\nTest Case 3: Weather ID 771 (Squalls)");
mockWeatherId = 771;
mockWeatherMain = "Squall";
mockWeatherDescription = "squalls";
const result3 = await getWeather(args, secrets);
console.log(`Weather ID: ${mockWeatherId}, Description: ${mockWeatherDescription}`);
console.log(`Mapped to enum: ${result3[0]} (${getWeatherName(result3[0])})`);
console.log(`Issue: Squalls are mapped to WINDY by default, but are more severe than regular wind`);
console.log("\nTest Case 4: Weather ID 300 (Light drizzle) vs 502 (Heavy rain)");
mockWeatherId = 300;
mockWeatherMain = "Drizzle";
mockWeatherDescription = "light intensity drizzle";
const result4a = await getWeather(args, secrets);
mockWeatherId = 502;
mockWeatherMain = "Rain";
mockWeatherDescription = "heavy intensity rain";
const result4b = await getWeather(args, secrets);
console.log(`Light drizzle (ID: 300) mapped to: ${getWeatherName(result4a[0])} (${result4a[0]})`);
console.log(`Heavy rain (ID: 502) mapped to: ${getWeatherName(result4b[0])} (${result4b[0]})`);
console.log(`Issue: Both light drizzle and heavy rain are mapped to the same RAINY state, despite significant intensity difference`);
console.log("\nTest Case 5: Weather ID 602 (Heavy snow) vs 600 (Light snow)");
mockWeatherId = 600;
mockWeatherMain = "Snow";
mockWeatherDescription = "light snow";
const result5a = await getWeather(args, secrets);
mockWeatherId = 602;
mockWeatherMain = "Snow";
mockWeatherDescription = "heavy snow";
const result5b = await getWeather(args, secrets);
console.log(`Light snow (ID: 600) mapped to: ${getWeatherName(result5a[0])} (${result5a[0]})`);
console.log(`Heavy snow (ID: 602) mapped to: ${getWeatherName(result5b[0])} (${result5b[0]})`);
console.log(`Issue: Both light and heavy snow are mapped to the same SNOW state, despite significant intensity difference`);
}
function getWeatherName(enumValue) {
const weatherNames = ["SUNNY", "CLOUDY", "RAINY", "THUNDERSTORM", "WINDY", "SNOW"];
return weatherNames[enumValue] || "UNKNOWN";
}
runTests();
The limited mapping reduces the accuracy and detail of the weather representation in the NFTs, potentially leading to confusion when users see a generic weather state that doesn't match the actual conditions.