This commit is contained in:
2025-11-29 18:00:49 +00:00
parent 6dd745f46c
commit 4e8f0017c7

137
covid.py
View File

@@ -11,6 +11,25 @@ import datetime
from html import escape
from tabulate import tabulate
def clean_text(text):
"""Clean text by removing problematic characters that cause encoding issues."""
if text is None:
return ''
# Convert to string if not already
text = str(text)
# Remove the problematic 'Â' character that appears with degree symbols
text = text.replace('\u00a0', ' ') # Non-breaking space to regular space
text = text.replace('\xc2', '') # Remove standalone  character
text = text.replace('°', '°') # Fix degree symbol encoding issue
text = text.replace('°F', '°F') # Fix degree F encoding issue
text = text.replace('°C', '°C') # Fix degree C encoding issue
text = text.replace('\u00a0', ' ') # Remove non-breaking spaces
text = text.encode('utf-8', errors='ignore').decode('utf-8') # Handle other encoding issues
return text
allobs = []
states = ['wv', 'oh', 'va', 'ky']
@@ -55,13 +74,13 @@ try:
finalobs = []
for obs in allobs:
tempob = [
obs.get('DateTimeStamp', ''),
obs.get('StationNumber', ''),
obs.get('StationName', ''),
obs.get('TotalPrecipAmt', ''),
obs.get('NewSnowDepth', ''),
obs.get('TotalSnowDepth', ''),
obs.get('Notes', '')
clean_text(obs.get('DateTimeStamp', '')),
clean_text(obs.get('StationNumber', '')),
clean_text(obs.get('StationName', '')),
clean_text(obs.get('TotalPrecipAmt', '')),
clean_text(obs.get('NewSnowDepth', '')),
clean_text(obs.get('TotalSnowDepth', '')),
clean_text(obs.get('Notes', ''))
]
finalobs.append(tempob)
@@ -78,27 +97,30 @@ try:
html_content = """<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Cocorahs Weather Data - """ + datewanted + """</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; font-weight: bold; }
th { background-color: #f2f2f2; font-weight: bold; cursor: pointer; }
th:hover { background-color: #e0e0e0; }
tr:nth-child(even) { background-color: #f9f9f9; }
.sort-arrow { margin-left: 5px; font-size: 0.8em; }
</style>
</head>
<body>
<h1>Cocorahs Weather Data - """ + datewanted + """</h1>
<table>
<table id="dataTable">
<thead>
<tr>
<th>Date/Time of Ob (Z)</th>
<th>Station Number</th>
<th>Station Name</th>
<th>New Precip</th>
<th>New Snow</th>
<th>Snow Depth</th>
<th>Comments</th>
<th onclick="sortTable(0)" title="Click to sort by Date/Time">Date/Time of Ob (Z)<span class="sort-arrow"></span></th>
<th onclick="sortTable(1)" title="Click to sort by Station Number">Station Number<span class="sort-arrow"></span></th>
<th onclick="sortTable(2)" title="Click to sort by Station Name">Station Name<span class="sort-arrow"></span></th>
<th onclick="sortTable(3)" title="Click to sort by New Precip">New Precip<span class="sort-arrow"></span></th>
<th onclick="sortTable(4)" title="Click to sort by New Snow">New Snow<span class="sort-arrow"></span></th>
<th onclick="sortTable(5)" title="Click to sort by Snow Depth">Snow Depth<span class="sort-arrow"></span></th>
<th onclick="sortTable(6)" title="Click to sort by Comments">Comments<span class="sort-arrow"></span></th>
</tr>
</thead>
<tbody>
@@ -112,6 +134,89 @@ try:
html_content += """ </tbody>
</table>
<script>
let sortDirection = Array(7).fill(true); // true for ascending, false for descending for 7 columns
function sortTable(columnIndex) {
const table = document.getElementById('dataTable');
const tbody = table.querySelector('tbody');
const rows = Array.from(tbody.rows);
// Determine the data type for this column
let isNumeric = [3, 4, 5].includes(columnIndex); // New Precip, New Snow, Snow Depth are numeric
let isDateTime = columnIndex === 0; // Date/Time is special
// Toggle sort direction
sortDirection[columnIndex] = !sortDirection[columnIndex];
const direction = sortDirection[columnIndex];
rows.sort((a, b) => {
const aCell = a.cells[columnIndex].textContent.trim();
const bCell = b.cells[columnIndex].textContent.trim();
let comparison = 0;
if (isDateTime) {
// Parse date for comparison (assuming format like: MM/DD/YYYY HH:MM:SS)
const dateA = parseDateTime(aCell);
const dateB = parseDateTime(bCell);
comparison = dateA - dateB;
} else if (isNumeric) {
// Convert to numeric values for comparison
const numA = parseFloat(aCell) || 0;
const numB = parseFloat(bCell) || 0;
comparison = numA - numB;
} else {
// Text comparison for A-Z/Z-A
comparison = aCell.localeCompare(bCell, undefined, {numeric: true, sensitivity: 'base'});
}
return direction ? comparison : -comparison;
});
// Reorder the rows in the table
rows.forEach(row => tbody.appendChild(row));
// Update sort arrows
updateSortArrows(columnIndex, direction);
}
function parseDateTime(dateString) {
// Handle various date formats, default to string if not parseable
if (!dateString || dateString.trim() === '') {
return 0;
}
// Try to parse date in common formats
let date = new Date(dateString);
if (isNaN(date)) {
// Try alternative parsing if the default doesn't work
const parts = dateString.replace(',', '').split(/[\s\/:]+/);
if (parts.length >= 3) {
// Assuming MM/DD/YYYY format
date = new Date(parts[2], parts[0] - 1, parts[1]);
}
}
return date.getTime ? date.getTime() : 0;
}
function updateSortArrows(columnIndex, direction) {
// Clear all arrows first
const allArrows = document.querySelectorAll('.sort-arrow');
allArrows.forEach(arrow => arrow.textContent = '');
// Set arrow for the current column
const currentArrow = document.querySelectorAll('.sort-arrow')[columnIndex];
currentArrow.textContent = direction ? '' : '';
}
// Initialize arrows on load
document.addEventListener('DOMContentLoaded', function() {
const arrows = document.querySelectorAll('.sort-arrow');
arrows.forEach(arrow => arrow.textContent = '');
});
</script>
</body>
</html>"""