1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="apple-mobile-web-app-title" content="AZ Weather">
<title>Arizona Weather Dashboard</title>
<link href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMl8U/zpsIv8+cyz/PXEp/zFdHf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEaQZv8+div/QXsx/0B6MP83ax3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7dib/QX0x/0WEPf9Egzv/O3Um/zhtIP83bR//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQIEw/0aKQP9Jjkb/SI1F/0CBMP9BhDP/QYUz/0icbf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALVQP/0WOPf9LlUn/TZlO/0yYTf9FjT3/S5pL/0uaS/9Lmkv/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQIAv/z58Kv9KmUv/T59S/1GhVf9QoFT/SphK/1SlVv9UpVb/UqJU/wAAAAAAAAAAAAAAAAAAAAAAAAAAM2Ah/0eTQ/9GkUD/T6BW/zJfIP9XrGv/VKZd/zRiI/8AAAAAUodP/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEuaS/9KmEn/SZdI/1SnYf9YqmX/Wqxm/1uwb/9TpmD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRoVL/UKBR/0+eT/9iuof/ZLNx/2W0cf9ls3D/YK5u/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWKpa/1aoWf9Vp1f/cbp+/2+7fv9wu3z/cLt8/z9xM/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABap1r/AAAAAHC7ev9vu3n/cL15/2+7ef8yXR//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIB4fCwAAAABmtmn/Z7dr/2i4bP9fqmD/ZbRo/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY7Vl/2W2Z/9mt2n/Zrdo/02PT/8YGiAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABltmf/Zrdp/2a3aP8AAAAAJCctAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAPwfAAD8HwAA/AcAAPwDAAD4AwAA8AMAAOAXAADgHwAA4B8AAOAfAAD0HwAA/B8AAPwfAAD+PwAA//8AAA==" rel="icon" type="image/x-icon" />
<link rel="apple-touch-icon" href="/static/apple-touch-icon.png" />
<link rel="stylesheet" type="text/css" href="/static/main.css">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<script>
const updated_at = {{ updated_at | json_encode() | safe }};
async function checkFreshness(backoff = 1000) {
const nextBackoff = Math.min(backoff * 2, 60000);
try {
const res = await fetch('/is_data_fresh');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fresh = await res.json();
if (fresh) {
location.reload();
} else {
setTimeout(() => checkFreshness(nextBackoff), backoff);
}
} catch (err) {
console.error('Fetch error:', err);
setTimeout(() => checkFreshness(nextBackoff), backoff);
}
}
</script>
</head>
<body>
<div class="header sticky">
<a class="github" href="https://www.github.com/rparrett/weather_dashboard"><svg aria-labelledby="simpleicons-github-icon" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title id="simpleicons-github-icon">GitHub icon</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path></svg></a>
<div>
Powered By <a href="https://pirateweather.net/en/latest/">Pirate Weather</a><br/>
Last updated <strong class="updated_at">{{ updated_at | time_ago }}</strong> ago.
{% if needs_update %}
<noscript>
Please refresh the page to get fresh data.
</noscript>
<span id="freshening" class="animated-ellipsis">Freshening</span>
<script>
document.getElementById("freshening").style.display = 'inline';
checkFreshness();
</script>
{% endif %}
</div>
</div>
{% for forecast in forecasts %}
<div class="location sticky">
<strong>{{forecast.location.name}}</strong>
{% if forecast.location.link %}[<a href="{{forecast.location.link}}">mp</a>] {% endif %}
[<a href="https://merrysky.net/forecast/{{forecast.location.latitude}},{{forecast.location.longitude}}/us">merry</a>]
[<a href="https://forecast.weather.gov/MapClick.php?lat={{forecast.location.latitude}}&lon={{forecast.location.longitude}}">nws</a>]
</div>
<div class="days">
{% for day in forecast.days %}
<div class="day {% if day.is_weekend %} weekend{% endif %}">
<div class="time">
<div>{{day.week_day}}</div>
<div>{{day.date}}</div>
</div>
<hr>
<div class="temps">
<div class="temp-label"><strong>H</strong></div>
<div class="temp {{day.temperature_high | temperature_class}}">{{day.temperature_high | round}}</div>
<div class="temp-label"><strong>fl</strong></div>
<div class="temp"><span class="{{day.temperature_high | temperature_class}}">{{day.apparent_temperature_high | round}}</span></div>
</div>
<div class="temps">
<div class="temp-label">L</div>
<div class="temp {{day.temperature_low | temperature_class}}">{{day.temperature_low | round}}</div>
<div class="temp-label">fl</div>
<div class="temp"><span class="{{day.temperature_low | temperature_class}}">{{day.apparent_temperature_low | round}}</span></div>
</div>
<div class="temps">
<div class="temp-label">P</div>
<div class="temp {{day.precip_probability | precip_class}}">{{day.precip_probability | probability }}</div>
<div class="temp-label">W</div>
<div class="temp">{{day.wind_speed | round }}</div>
</div>
<hr>
<div class="summary-cell"><span>{{day.summary}}</span></div>
</div>
{% endfor %}
</div>
{% endfor %}
</body>
</html>