Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions eco_project/backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,108 @@ def youtube_videos():
return jsonify({"error": str(e)}), 500


@app.route('/api/unep_recycling')
def unep_recycling():
# SDG Indicator 12.5.1: National recycling rate
# Series: EN_MWT_RCYR (Proportion of municipal waste recycled (%))
# UNEP is the custodian of this indicator.
url = "https://unstats.un.org/SDGAPI/v1/sdg/Series/Data?seriesCode=EN_MWT_RCYR&pageSize=1000"

try:
response = requests.get(url, timeout=10)
data = response.json()

if data and data.get('data'):
latest_data = {}
for entry in data['data']:
country = entry['geoAreaName']
year = entry['timePeriodStart']
value = entry['value']

if value is not None and (country not in latest_data or year > latest_data[country]['year']):
latest_data[country] = {
'country': country,
'year': int(year),
'value': float(value)
Comment on lines +749 to +753
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Comparison between year (string) and stored year (int) will raise a TypeError.

year comes directly from the API as a string, while latest_data[country]['year'] is stored as int(year). On subsequent iterations this makes year > latest_data[country]['year'] a string-vs-int comparison in Python 3. Convert year once (e.g. year_int = int(year)) and use year_int both in the comparison and when storing it.

}

# Top 10 countries
formatted_data = sorted(latest_data.values(), key=lambda x: x['value'], reverse=True)[:10]

logger.log_struct(
{
"message": "Successfully fetched UNEP recycling data.",
"component": "backend",
"endpoint": "/api/unep_recycling",
},
severity="INFO",
)
return jsonify(formatted_data)
else:
return jsonify({"error": "No data found"}), 404
except Exception as e:
logger.log_struct(
{
"message": f"Error fetching UNEP data: {e}",
"component": "backend",
"endpoint": "/api/unep_recycling",
},
severity="ERROR",
)
return jsonify({"error": str(e)}), 500


@app.route('/api/unep_protected_areas')
def unep_protected_areas():
# SDG Indicator 15.1.2: Protected areas
# Series: ER_PTD_TERR (Average proportion of Terrestrial KBAs covered by protected areas (%))
# UNEP is the custodian of this indicator.
url = "https://unstats.un.org/SDGAPI/v1/sdg/Series/Data?seriesCode=ER_PTD_TERR&pageSize=1000"

try:
response = requests.get(url, timeout=10)
data = response.json()

if data and data.get('data'):
latest_data = {}
for entry in data['data']:
country = entry['geoAreaName']
year = entry['timePeriodStart']
value = entry['value']

if value is not None and (country not in latest_data or year > latest_data[country]['year']):
latest_data[country] = {
'country': country,
'year': int(year),
'value': float(value)
}

# Top 10 countries
formatted_data = sorted(latest_data.values(), key=lambda x: x['value'], reverse=True)[:10]

logger.log_struct(
{
"message": "Successfully fetched UNEP protected areas data.",
"component": "backend",
"endpoint": "/api/unep_protected_areas",
},
severity="INFO",
)
return jsonify(formatted_data)
else:
return jsonify({"error": "No data found"}), 404
except Exception as e:
logger.log_struct(
{
"message": f"Error fetching UNEP data: {e}",
"component": "backend",
"endpoint": "/api/unep_protected_areas",
},
severity="ERROR",
)
return jsonify({"error": str(e)}), 500


if __name__ == '__main__':
port = int(os.environ.get("PORT", 8080))
socketio.run(app, host='0.0.0.0', port=port, debug=False, allow_unsafe_werkzeug=True)
1 change: 1 addition & 0 deletions eco_project/backend/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ <h2>Community</h2>
<li><a href="chat.html">Join the Chat</a></li>
<li><a href="sports.html">Watch Sports</a></li>
<li><a href="air_quality.html">Air Quality</a></li>
<li><a href="unep.html">UNEP Data</a></li>
</ul>
</section>
<section id="ai-agent">
Expand Down
29 changes: 29 additions & 0 deletions eco_project/backend/static/unep.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
main {
padding: 20px;
max-width: 1000px;
margin: 0 auto;
}

section {
margin-bottom: 40px;
padding: 20px;
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

h2 {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 10px;
}

canvas {
max-width: 100%;
height: auto;
}

#unep-intro {
background-color: #e8f4f8;
border-left: 5px solid #3498db;
}
41 changes: 41 additions & 0 deletions eco_project/backend/static/unep.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>UNEP Data - Environment Protection</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="unep.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<header>
<h1>UN Environment Programme (UNEP) Data</h1>
<nav>
<a href="index.html">Home</a>
</nav>
</header>
<main>
<section id="unep-intro">
<h2>UNEP and the SDGs</h2>
<p>The United Nations Environment Programme (UNEP) is the leading global authority on the environment. It is the custodian for many Sustainable Development Goal (SDG) indicators. Below is data for two key indicators custodianed by UNEP.</p>
</section>

<section id="recycling-data">
<h2>National Recycling Rate (SDG 12.5.1)</h2>
<p>Proportion of municipal waste recycled (%) - Top 10 Countries</p>
<canvas id="recyclingChart"></canvas>
</section>

<section id="protected-areas-data">
<h2>Protected Areas (SDG 15.1.2)</h2>
<p>Average proportion of Terrestrial Key Biodiversity Areas (KBAs) covered by protected areas (%) - Top 10 Countries</p>
<canvas id="protectedAreasChart"></canvas>
</section>
</main>
<footer>
<p>&copy; 2025 Environment Protection Initiative</p>
</footer>
<script src="unep.js"></script>
</body>
</html>
56 changes: 56 additions & 0 deletions eco_project/backend/static/unep.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
fetchRecyclingData();
fetchProtectedAreasData();

function fetchRecyclingData() {
fetch('/api/unep_recycling')
.then(response => response.json())
.then(data => {
if (data.error) {
console.error('Error fetching recycling data:', data.error);
return;
}
renderChart('recyclingChart', data, 'Recycling Rate (%)', 'rgba(75, 192, 192, 0.2)', 'rgba(75, 192, 192, 1)');
})
.catch(error => console.error('Error:', error));
}

function fetchProtectedAreasData() {
fetch('/api/unep_protected_areas')
.then(response => response.json())
.then(data => {
if (data.error) {
console.error('Error fetching protected areas data:', data.error);
return;
}
renderChart('protectedAreasChart', data, 'Protected Area Coverage (%)', 'rgba(153, 102, 255, 0.2)', 'rgba(153, 102, 255, 1)');
})
.catch(error => console.error('Error:', error));
}

function renderChart(canvasId, data, label, bgColor, borderColor) {
const ctx = document.getElementById(canvasId).getContext('2d');
const labels = data.map(item => item.country);
const values = data.map(item => item.value);

new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: label,
data: values,
backgroundColor: bgColor,
borderColor: borderColor,
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true,
max: 100
}
}
}
});
}
Loading