diff --git a/src/render/formatted.zig b/src/render/formatted.zig
index 1d38a13..c8c6f30 100644
--- a/src/render/formatted.zig
+++ b/src/render/formatted.zig
@@ -90,7 +90,7 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
const precip_unit = if (options.use_imperial) "in" else "mm";
const precip = if (options.use_imperial) current.precip_mm * 0.0393701 else current.precip_mm;
- const art = getWeatherArt(current.weather_code);
+ const art = getWeatherArt(current.weather_code, options.format);
const sign: u8 = if (temp >= 0) '+' else '-';
const abs_temp = @abs(temp);
const fl_sign: u8 = if (feels_like >= 0) '+' else '-';
@@ -113,37 +113,35 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
.ansi => {
const temp_color_code = tempColor(current.temp_c);
const wind_color_code = windColor(current.wind_kph);
- const cloud_color = "\x1b[38;5;250m";
const reset = "\x1b[0m";
- try w.print("{s}{s}{s} {s}\n", .{ cloud_color, art[0], reset, current.condition });
- try w.print("{s}{s}{s} \x1b[38;5;{d}m{c}{d:.0}({c}{d:.0}){s} {s}\n", .{ cloud_color, art[1], reset, temp_color_code, sign, abs_temp, fl_sign, abs_fl, reset, temp_unit });
- try w.print("{s}{s}{s} {s} \x1b[38;5;{d}m{d:.0}{s} {s}\n", .{ cloud_color, art[2], reset, degreeToArrow(current.wind_deg), wind_color_code, wind_speed, reset, wind_unit });
+ try w.print("{s} {s}\n", .{ art[0], current.condition });
+ try w.print("{s} \x1b[38;5;{d}m{c}{d:.0}({c}{d:.0}){s} {s}\n", .{ art[1], temp_color_code, sign, abs_temp, fl_sign, abs_fl, reset, temp_unit });
+ try w.print("{s} {s} \x1b[38;5;{d}m{d:.0}{s} {s}\n", .{ art[2], degreeToArrow(current.wind_deg), wind_color_code, wind_speed, reset, wind_unit });
if (current.visibility_km) |_| {
const visibility = if (options.use_imperial) current.visiblityMph().? else current.visibility_km.?;
const vis_unit = if (options.use_imperial) "mi" else "km";
- try w.print("{s}{s}{s} {d:.0} {s}\n", .{ cloud_color, art[3], reset, visibility, vis_unit });
+ try w.print("{s} {d:.0} {s}\n", .{ art[3], visibility, vis_unit });
} else {
- try w.print("{s}{s}{s}\n", .{ cloud_color, std.mem.trimRight(u8, art[3], " "), reset });
+ try w.print("{s}\n", .{std.mem.trimRight(u8, art[3], " ")});
}
- try w.print("{s}{s}{s} {d:.1} {s}\n", .{ cloud_color, art[4], reset, precip, precip_unit });
+ try w.print("{s} {d:.1} {s}\n", .{ art[4], precip, precip_unit });
},
.html => {
const temp_color = ansiToHex(tempColor(current.temp_c));
const wind_color = ansiToHex(windColor(current.wind_kph));
- const cloud_color = "#bcbcbc"; // 250
- try w.print("{s} {s}\n", .{ cloud_color, art[0], current.condition });
- try w.print("{s} {c}{d:.0}({c}{d:.0}) {s}\n", .{ cloud_color, art[1], temp_color, sign, abs_temp, fl_sign, abs_fl, temp_unit });
- try w.print("{s} {s} {d:.0} {s}\n", .{ cloud_color, art[2], degreeToArrow(current.wind_deg), wind_color, wind_speed, wind_unit });
+ try w.print("{s} {s}\n", .{ art[0], current.condition });
+ try w.print("{s} {c}{d:.0}({c}{d:.0}) {s}\n", .{ art[1], temp_color, sign, abs_temp, fl_sign, abs_fl, temp_unit });
+ try w.print("{s} {s} {d:.0} {s}\n", .{ art[2], degreeToArrow(current.wind_deg), wind_color, wind_speed, wind_unit });
if (current.visibility_km) |_| {
const visibility = if (options.use_imperial) current.visiblityMph().? else current.visibility_km.?;
const vis_unit = if (options.use_imperial) "mi" else "km";
- try w.print("{s} {d:.0} {s}\n", .{ cloud_color, art[3], visibility, vis_unit });
+ try w.print("{s} {d:.0} {s}\n", .{ art[3], visibility, vis_unit });
} else {
- try w.print("{s}\n", .{ cloud_color, std.mem.trimRight(u8, art[3], " ") });
+ try w.print("{s}\n", .{std.mem.trimRight(u8, art[3], " ")});
}
- try w.print("{s} {d:.1} {s}\n", .{ cloud_color, art[4], precip, precip_unit });
+ try w.print("{s} {d:.1} {s}\n", .{ art[4], precip, precip_unit });
},
}
}
@@ -154,7 +152,7 @@ fn renderForecastDay(w: *std.Io.Writer, day: types.ForecastDay, options: RenderO
const max_temp = if (options.use_imperial) day.maxTempFahrenheit() else day.max_temp_c;
const min_temp = if (options.use_imperial) day.minTempFahrenheit() else day.min_temp_c;
const temp_unit = if (options.use_imperial) "°F" else "°C";
- const art = getWeatherArt(day.weather_code);
+ const art = getWeatherArt(day.weather_code, options.format);
_ = try formatDate(day.date, .compressed, &date_str);
try w.print("\n{s}\n", .{std.mem.trimEnd(u8, date_str[0..], " ")});
@@ -199,7 +197,7 @@ fn renderHourlyCell(w: *std.Io.Writer, hour: types.HourlyForecast, line: usize,
precipitation = 4,
};
- const art = getWeatherArt(hour.weather_code);
+ const art = getWeatherArt(hour.weather_code, options.format);
const total_width = 28;
const art_width = 14; // includes spacer between art and data. This is display width, not actual
@@ -207,17 +205,7 @@ fn renderHourlyCell(w: *std.Io.Writer, hour: types.HourlyForecast, line: usize,
var cell_writer = std.Io.Writer.fixed(&buf);
const cw = &cell_writer;
- switch (options.format) {
- .ansi => {
- try w.print("\x1b[38;5;250m{s}\x1b[0m ", .{art[line]});
- },
- .html => {
- try w.print("{s} ", .{art[line]});
- },
- .plain_text => {
- try w.print("{s} ", .{art[line]});
- },
- }
+ try w.print("{s} ", .{art[line]});
switch (@as(Line, @enumFromInt(line))) {
.condition => {
@@ -408,7 +396,15 @@ fn ansiToHex(code: u8) []const u8 {
};
}
-fn getWeatherArt(code: types.WeatherCode) [5][]const u8 {
+fn getWeatherArt(code: types.WeatherCode, format: Format) [5][]const u8 {
+ return switch (format) {
+ .plain_text => getWeatherArtPlain(code),
+ .ansi => getWeatherArtAnsi(code),
+ .html => getWeatherArtHtml(code),
+ };
+}
+
+fn getWeatherArtPlain(code: types.WeatherCode) [5][]const u8 {
return switch (@intFromEnum(code)) {
800 => .{ // Clear
" \\ / ",
@@ -476,6 +472,142 @@ fn getWeatherArt(code: types.WeatherCode) [5][]const u8 {
};
}
+fn getWeatherArtAnsi(code: types.WeatherCode) [5][]const u8 {
+ return switch (@intFromEnum(code)) {
+ 800 => .{ // Clear
+ "\x1b[38;5;226m \\ / \x1b[0m",
+ "\x1b[38;5;226m .-. \x1b[0m",
+ "\x1b[38;5;226m ― ( ) ― \x1b[0m",
+ "\x1b[38;5;226m `-' \x1b[0m",
+ "\x1b[38;5;226m / \\ \x1b[0m",
+ },
+ 801, 802 => .{ // Partly cloudy
+ "\x1b[38;5;226m \\ /\x1b[0m ",
+ "\x1b[38;5;226m _ /\"\"\x1b[38;5;250m.-. \x1b[0m",
+ "\x1b[38;5;226m \\_\x1b[38;5;250m( ). \x1b[0m",
+ "\x1b[38;5;226m /\x1b[38;5;250m(___(__) \x1b[0m",
+ " ",
+ },
+ 803, 804 => .{ // Cloudy
+ " ",
+ "\x1b[38;5;250m .--. \x1b[0m",
+ "\x1b[38;5;250m .-( ). \x1b[0m",
+ "\x1b[38;5;250m (___.__)__) \x1b[0m",
+ " ",
+ },
+ 300...321, 500...531 => .{ // Drizzle/Rain
+ "\x1b[38;5;250m .-. \x1b[0m",
+ "\x1b[38;5;250m ( ). \x1b[0m",
+ "\x1b[38;5;250m (___(__) \x1b[0m",
+ "\x1b[38;5;111m ʻ ʻ ʻ ʻ \x1b[0m",
+ "\x1b[38;5;111m ʻ ʻ ʻ ʻ \x1b[0m",
+ },
+ 200...232 => .{ // Thunderstorm
+ "\x1b[38;5;250m .-. \x1b[0m",
+ "\x1b[38;5;250m ( ). \x1b[0m",
+ "\x1b[38;5;250m (___(__) \x1b[0m",
+ "\x1b[38;5;228;5m ⚡\x1b[38;5;111;25mʻʻ\x1b[38;5;228;5m⚡\x1b[38;5;111;25mʻʻ\x1b[0m",
+ "\x1b[38;5;111m ʻ ʻ ʻ ʻ \x1b[0m",
+ },
+ 600...610, 617...622 => .{ // Snow
+ "\x1b[38;5;250m .-. \x1b[0m",
+ "\x1b[38;5;250m ( ). \x1b[0m",
+ "\x1b[38;5;250m (___(__) \x1b[0m",
+ "\x1b[38;5;255m * * * \x1b[0m",
+ "\x1b[38;5;255m * * * \x1b[0m",
+ },
+ 611...616 => .{ // Sleet
+ "\x1b[38;5;250m .-. \x1b[0m",
+ "\x1b[38;5;250m ( ). \x1b[0m",
+ "\x1b[38;5;250m (___(__) \x1b[0m",
+ "\x1b[38;5;111m ʻ \x1b[38;5;255m*\x1b[38;5;111m ʻ \x1b[38;5;255m* \x1b[0m",
+ "\x1b[38;5;255m *\x1b[38;5;111m ʻ \x1b[38;5;255m*\x1b[38;5;111m ʻ \x1b[0m",
+ },
+ 701, 741 => .{ // Fog
+ " ",
+ "\x1b[38;5;251m _ - _ - _ - \x1b[0m",
+ "\x1b[38;5;251m _ - _ - _ \x1b[0m",
+ "\x1b[38;5;251m _ - _ - _ - \x1b[0m",
+ " ",
+ },
+ else => .{ // Unknown
+ " ",
+ " ? ",
+ " ¯\\_(ツ)_/¯ ",
+ " ",
+ " ",
+ },
+ };
+}
+
+fn getWeatherArtHtml(code: types.WeatherCode) [5][]const u8 {
+ return switch (@intFromEnum(code)) {
+ 800 => .{ // Clear
+ " \\ / ",
+ " .-. ",
+ " ― ( ) ― ",
+ " `-' ",
+ " / \\ ",
+ },
+ 801, 802 => .{ // Partly cloudy
+ " \\ / ",
+ " _ /\"\".-. ",
+ " \\_( ). ",
+ " /(___(__) ",
+ " ",
+ },
+ 803, 804 => .{ // Cloudy
+ " ",
+ " .--. ",
+ " .-( ). ",
+ " (___.__)__) ",
+ " ",
+ },
+ 300...321, 500...531 => .{ // Drizzle/Rain
+ " .-. ",
+ " ( ). ",
+ " (___(__) ",
+ " ʻ ʻ ʻ ʻ ",
+ " ʻ ʻ ʻ ʻ ",
+ },
+ 200...232 => .{ // Thunderstorm
+ " .-. ",
+ " ( ). ",
+ " (___(__) ",
+ " ⚡ʻ⚡ʻ ",
+ " ʻ ʻ ʻ ",
+ },
+ 600...610, 617...622 => .{ // Snow
+ " .-. ",
+ " ( ). ",
+ " (___(__) ",
+ " * * * ",
+ " * * * ",
+ },
+ 611...616 => .{ // Sleet
+ " .-. ",
+ " ( ). ",
+ " (___(__) ",
+ " ʻ * ʻ * ",
+ " * ʻ * ʻ ",
+ },
+ 701, 741 => .{ // Fog
+ " ",
+ " _ - _ - _ - ",
+ " _ - _ - _ ",
+ " _ - _ - _ - ",
+ " ",
+ },
+ else => .{ // Unknown
+ " ",
+ " ? ",
+ " ¯\\_(ツ)_/¯ ",
+ " ",
+ " ",
+ },
+ };
+}
+
test "render with imperial units" {
const data = types.WeatherData{
.location = "Chicago",
@@ -523,11 +655,7 @@ test "clear weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, "\\ /") != null);
- try std.testing.expect(std.mem.indexOf(u8, output, "( )") != null);
+ try testArt(data);
}
test "partly cloudy weather art" {
@@ -549,11 +677,35 @@ test "partly cloudy weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
+ try testArt(data);
+}
- try std.testing.expect(std.mem.indexOf(u8, output, "\"\".-.") != null);
- try std.testing.expect(std.mem.indexOf(u8, output, "\\_( )") != null);
+/// Tests to make sure the weather art shows up in the rendering for all formats
+fn testArt(data: types.WeatherData) !void {
+ inline for (std.meta.fields(Format)) |f| {
+ const format: Format = @enumFromInt(f.value);
+ const output = try render(
+ std.testing.allocator,
+ data,
+ .{ .format = format },
+ );
+ defer std.testing.allocator.free(output);
+
+ const target = getWeatherArt(
+ data.current.weather_code,
+ format,
+ );
+ for (target, 1..) |line, i| {
+ const trimmed = std.mem.trimRight(u8, line, " ");
+ std.testing.expect(std.mem.indexOf(u8, output, trimmed) != null) catch |e| {
+ std.log.err(
+ "Test failure, weather code {}, format {}, line {d}. Line '{s}', Output:\n{s}\n",
+ .{ data.current.weather_code, format, i, line, output },
+ );
+ return e;
+ };
+ }
+ }
}
test "cloudy weather art" {
@@ -575,11 +727,7 @@ test "cloudy weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, ".--.") != null);
- try std.testing.expect(std.mem.indexOf(u8, output, "(___.__)__)") != null);
+ try testArt(data);
}
test "rain weather art" {
@@ -601,10 +749,7 @@ test "rain weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, "ʻ ʻ ʻ ʻ") != null);
+ try testArt(data);
}
test "thunderstorm weather art" {
@@ -626,10 +771,7 @@ test "thunderstorm weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, "⚡") != null);
+ try testArt(data);
}
test "snow weather art" {
@@ -651,10 +793,7 @@ test "snow weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, "* * *") != null);
+ try testArt(data);
}
test "sleet weather art" {
@@ -676,10 +815,7 @@ test "sleet weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, "ʻ * ʻ *") != null);
+ try testArt(data);
}
test "fog weather art" {
@@ -701,10 +837,7 @@ test "fog weather art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, "_ - _ - _ -") != null);
+ try testArt(data);
}
test "unknown weather code art" {
@@ -726,11 +859,7 @@ test "unknown weather code art" {
.allocator = std.testing.allocator,
};
- const output = try render(std.testing.allocator, data, .{});
- defer std.testing.allocator.free(output);
-
- try std.testing.expect(std.mem.indexOf(u8, output, "?") != null);
- try std.testing.expect(std.mem.indexOf(u8, output, "¯\\_(ツ)_/¯") != null);
+ try testArt(data);
}
test "temperature matches between ansi and custom format" {
diff --git a/src/tests/metno-phoenix-tmp.ansi b/src/tests/metno-phoenix-tmp.ansi
index 5d612e7..1b87c82 100644
--- a/src/tests/metno-phoenix-tmp.ansi
+++ b/src/tests/metno-phoenix-tmp.ansi
@@ -1,38 +1,38 @@
Weather report: 33.4484,-112.0741
-[38;5;250m [0m Cloudy
+ Cloudy
[38;5;250m .--. [0m [38;5;154m+61(+61)[0m °F
[38;5;250m .-( ). [0m ↘ [38;5;242m2[0m mph
-[38;5;250m (___.__)__)[0m
-[38;5;250m [0m 0.0 in
+[38;5;250m (___.__)__) [0m
+ 0.0 in
┌─────────────┐
┌──────────────────────────────┬───────────────────────┤ Sun 4 Jan ├───────────────────────┬──────────────────────────────┐
│ Morning │ Noon └──────┬──────┘ Evening │ Night │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
-│ [38;5;250m [0m Cloudy │ [38;5;250m \ / [0m Partly cloudy │ [38;5;250m \ / [0m Partly cloudy │ [38;5;250m \ / [0m Clear │
-│ [38;5;250m .--. [0m [38;5;154m+61(+61)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;118m+56(+56)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;82m+50(+50)[0m °F │ [38;5;250m .-. [0m [38;5;190m+65(+65)[0m °F │
-│ [38;5;250m .-( ). [0m ↘ [38;5;242m2[0m mph │ [38;5;250m \_( ). [0m ↖ [38;5;241m1[0m mph │ [38;5;250m \_( ). [0m ↖ [38;5;242m3[0m mph │ [38;5;250m ― ( ) ― [0m ↖ [38;5;242m3[0m mph │
-│ [38;5;250m (___.__)__) [0m │ [38;5;250m /(___(__) [0m │ [38;5;250m /(___(__) [0m │ [38;5;250m `-' [0m │
-│ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m / \ [0m 0.0 in | 0% │
+│ Cloudy │ [38;5;226m \ /[0m Partly cloudy │ [38;5;226m \ /[0m Partly cloudy │ [38;5;226m \ / [0m Clear │
+│ [38;5;250m .--. [0m [38;5;154m+61(+61)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;118m+56(+56)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;82m+50(+50)[0m °F │ [38;5;226m .-. [0m [38;5;190m+65(+65)[0m °F │
+│ [38;5;250m .-( ). [0m ↘ [38;5;242m2[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ↖ [38;5;241m1[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ↖ [38;5;242m3[0m mph │ [38;5;226m ― ( ) ― [0m ↖ [38;5;242m3[0m mph │
+│ [38;5;250m (___.__)__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │ [38;5;226m `-' [0m │
+│ 0.0 in | 0% │ 0.0 in | 0% │ 0.0 in | 0% │ [38;5;226m / \ [0m 0.0 in | 0% │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
┌─────────────┐
┌──────────────────────────────┬───────────────────────┤ Mon 5 Jan ├───────────────────────┬──────────────────────────────┐
│ Morning │ Noon └──────┬──────┘ Evening │ Night │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
-│ [38;5;250m \ / [0m Fair │ [38;5;250m \ / [0m Partly cloudy │ [38;5;250m \ / [0m Partly cloudy │ [38;5;250m \ / [0m Partly cloudy │
-│ [38;5;250m _ /"".-. [0m [38;5;190m+68(+68)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;118m+57(+57)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;82m+53(+53)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;154m+61(+61)[0m °F │
-│ [38;5;250m \_( ). [0m ↙ [38;5;241m2[0m mph │ [38;5;250m \_( ). [0m ↖ [38;5;242m3[0m mph │ [38;5;250m \_( ). [0m ↘ [38;5;242m2[0m mph │ [38;5;250m \_( ). [0m ← [38;5;242m3[0m mph │
-│ [38;5;250m /(___(__) [0m │ [38;5;250m /(___(__) [0m │ [38;5;250m /(___(__) [0m │ [38;5;250m /(___(__) [0m │
-│ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │
+│ [38;5;226m \ /[0m Fair │ [38;5;226m \ /[0m Partly cloudy │ [38;5;226m \ /[0m Partly cloudy │ [38;5;226m \ /[0m Partly cloudy │
+│ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;190m+68(+68)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;118m+57(+57)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;82m+53(+53)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;154m+61(+61)[0m °F │
+│ [38;5;226m \_[38;5;250m( ). [0m ↙ [38;5;241m2[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ↖ [38;5;242m3[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ↘ [38;5;242m2[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ← [38;5;242m3[0m mph │
+│ [38;5;226m /[38;5;250m(___(__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │
+│ 0.0 in | 0% │ 0.0 in | 0% │ 0.0 in | 0% │ 0.0 in | 0% │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
┌─────────────┐
┌──────────────────────────────┬───────────────────────┤ Tue 6 Jan ├───────────────────────┬──────────────────────────────┐
│ Morning │ Noon └──────┬──────┘ Evening │ Night │
├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
-│ [38;5;250m [0m Cloudy │ [38;5;250m \ / [0m Partly cloudy │ [38;5;250m \ / [0m Partly cloudy │ [38;5;250m \ / [0m Partly cloudy │
-│ [38;5;250m .--. [0m [38;5;190m+66(+66)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;118m+58(+58)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;82m+53(+53)[0m °F │ [38;5;250m _ /"".-. [0m [38;5;82m+49(+49)[0m °F │
-│ [38;5;250m .-( ). [0m ↘ [38;5;242m2[0m mph │ [38;5;250m \_( ). [0m ← [38;5;242m3[0m mph │ [38;5;250m \_( ). [0m ← [38;5;242m2[0m mph │ [38;5;250m \_( ). [0m ← [38;5;241m2[0m mph │
-│ [38;5;250m (___.__)__) [0m │ [38;5;250m /(___(__) [0m │ [38;5;250m /(___(__) [0m │ [38;5;250m /(___(__) [0m │
-│ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │ [38;5;250m [0m 0.0 in | 0% │
+│ Cloudy │ [38;5;226m \ /[0m Partly cloudy │ [38;5;226m \ /[0m Partly cloudy │ [38;5;226m \ /[0m Partly cloudy │
+│ [38;5;250m .--. [0m [38;5;190m+66(+66)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;118m+58(+58)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;82m+53(+53)[0m °F │ [38;5;226m _ /""[38;5;250m.-. [0m [38;5;82m+49(+49)[0m °F │
+│ [38;5;250m .-( ). [0m ↘ [38;5;242m2[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ← [38;5;242m3[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ← [38;5;242m2[0m mph │ [38;5;226m \_[38;5;250m( ). [0m ← [38;5;241m2[0m mph │
+│ [38;5;250m (___.__)__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │ [38;5;226m /[38;5;250m(___(__) [0m │
+│ 0.0 in | 0% │ 0.0 in | 0% │ 0.0 in | 0% │ 0.0 in | 0% │
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘