make art tests cover all formats more holistically
This commit is contained in:
parent
a314fc39d4
commit
ff571626db
2 changed files with 215 additions and 86 deletions
|
|
@ -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("<span style=\"color:{s}\">{s}</span> {s}\n", .{ cloud_color, art[0], current.condition });
|
||||
try w.print("<span style=\"color:{s}\">{s}</span> <span style=\"color:{s}\">{c}{d:.0}({c}{d:.0})</span> {s}\n", .{ cloud_color, art[1], temp_color, sign, abs_temp, fl_sign, abs_fl, temp_unit });
|
||||
try w.print("<span style=\"color:{s}\">{s}</span> {s} <span style=\"color:{s}\">{d:.0}</span> {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} <span style=\"color:{s}\">{c}{d:.0}({c}{d:.0})</span> {s}\n", .{ art[1], temp_color, sign, abs_temp, fl_sign, abs_fl, temp_unit });
|
||||
try w.print("{s} {s} <span style=\"color:{s}\">{d:.0}</span> {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("<span style=\"color:{s}\">{s}</span> {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("<span style=\"color:{s}\">{s}</span>\n", .{ cloud_color, std.mem.trimRight(u8, art[3], " ") });
|
||||
try w.print("{s}\n", .{std.mem.trimRight(u8, art[3], " ")});
|
||||
}
|
||||
try w.print("<span style=\"color:{s}\">{s}</span> {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("<span style=\"color:#bcbcbc\">{s}</span> ", .{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
|
||||
"<span style=\"color:#ffff00\"> \\ / </span>",
|
||||
"<span style=\"color:#ffff00\"> .-. </span>",
|
||||
"<span style=\"color:#ffff00\"> ― ( ) ― </span>",
|
||||
"<span style=\"color:#ffff00\"> `-' </span>",
|
||||
"<span style=\"color:#ffff00\"> / \\ </span>",
|
||||
},
|
||||
801, 802 => .{ // Partly cloudy
|
||||
"<span style=\"color:#ffff00\"> \\ / </span>",
|
||||
"<span style=\"color:#bcbcbc\"> _ /\"\".-. </span>",
|
||||
"<span style=\"color:#bcbcbc\"> \\_( ). </span>",
|
||||
"<span style=\"color:#bcbcbc\"> /(___(__) </span>",
|
||||
" ",
|
||||
},
|
||||
803, 804 => .{ // Cloudy
|
||||
" ",
|
||||
"<span style=\"color:#bcbcbc\"> .--. </span>",
|
||||
"<span style=\"color:#bcbcbc\"> .-( ). </span>",
|
||||
"<span style=\"color:#bcbcbc\"> (___.__)__) </span>",
|
||||
" ",
|
||||
},
|
||||
300...321, 500...531 => .{ // Drizzle/Rain
|
||||
"<span style=\"color:#bcbcbc\"> .-. </span>",
|
||||
"<span style=\"color:#bcbcbc\"> ( ). </span>",
|
||||
"<span style=\"color:#bcbcbc\"> (___(__) </span>",
|
||||
"<span style=\"color:#87afff\"> ʻ ʻ ʻ ʻ </span>",
|
||||
"<span style=\"color:#87afff\"> ʻ ʻ ʻ ʻ </span>",
|
||||
},
|
||||
200...232 => .{ // Thunderstorm
|
||||
"<span style=\"color:#bcbcbc\"> .-. </span>",
|
||||
"<span style=\"color:#bcbcbc\"> ( ). </span>",
|
||||
"<span style=\"color:#bcbcbc\"> (___(__) </span>",
|
||||
"<span style=\"color:#ffff87\"> ⚡</span><span style=\"color:#87afff\">ʻ</span><span style=\"color:#ffff87\">⚡</span><span style=\"color:#87afff\">ʻ </span>",
|
||||
"<span style=\"color:#87afff\"> ʻ ʻ ʻ </span>",
|
||||
},
|
||||
600...610, 617...622 => .{ // Snow
|
||||
"<span style=\"color:#bcbcbc\"> .-. </span>",
|
||||
"<span style=\"color:#bcbcbc\"> ( ). </span>",
|
||||
"<span style=\"color:#bcbcbc\"> (___(__) </span>",
|
||||
"<span style=\"color:#eeeeee\"> * * * </span>",
|
||||
"<span style=\"color:#eeeeee\"> * * * </span>",
|
||||
},
|
||||
611...616 => .{ // Sleet
|
||||
"<span style=\"color:#bcbcbc\"> .-. </span>",
|
||||
"<span style=\"color:#bcbcbc\"> ( ). </span>",
|
||||
"<span style=\"color:#bcbcbc\"> (___(__) </span>",
|
||||
"<span style=\"color:#87afff\"> ʻ </span><span style=\"color:#eeeeee\">*</span><span style=\"color:#87afff\"> ʻ </span><span style=\"color:#eeeeee\">* </span>",
|
||||
"<span style=\"color:#eeeeee\"> * </span><span style=\"color:#87afff\">ʻ</span><span style=\"color:#eeeeee\"> * </span><span style=\"color:#87afff\">ʻ </span>",
|
||||
},
|
||||
701, 741 => .{ // Fog
|
||||
" ",
|
||||
"<span style=\"color:#c6c6c6\"> _ - _ - _ - </span>",
|
||||
"<span style=\"color:#c6c6c6\"> _ - _ - _ </span>",
|
||||
"<span style=\"color:#c6c6c6\"> _ - _ - _ - </span>",
|
||||
" ",
|
||||
},
|
||||
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" {
|
||||
|
|
|
|||
|
|
@ -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% │
|
||||
└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue