diff --git a/src/http/handler.zig b/src/http/handler.zig
index 1e3df08..41f6528 100644
--- a/src/http/handler.zig
+++ b/src/http/handler.zig
@@ -425,7 +425,7 @@ test "handler: format line 1" {
try handleWeather(&harness.opts, ht.req, ht.res, client_ip);
try ht.expectStatus(200);
- try ht.expectBody("Test: ☀️ 20°C");
+ try ht.expectBody("☀️ +20°C");
}
test "handler: format line 2" {
@@ -446,7 +446,7 @@ test "handler: format line 2" {
try handleWeather(&harness.opts, ht.req, ht.res, client_ip);
try ht.expectStatus(200);
- try ht.expectBody("Test: ☀️ 20°C 🌬️N5km/h");
+ try ht.expectBody("☀️ 🌡️+20°C 🌬️↓5km/h");
}
test "handler: format line 3" {
@@ -467,5 +467,5 @@ test "handler: format line 3" {
try handleWeather(&harness.opts, ht.req, ht.res, client_ip);
try ht.expectStatus(200);
- try ht.expectBody("Test: ☀️ 20°C 🌬️N5km/h 💧50%%");
+ try ht.expectBody("Test: ☀️ +20°C");
}
diff --git a/src/render/Formatted.zig b/src/render/Formatted.zig
index 892aa39..6fc9132 100644
--- a/src/render/Formatted.zig
+++ b/src/render/Formatted.zig
@@ -1,6 +1,7 @@
const std = @import("std");
const types = @import("../weather/types.zig");
const zeit = @import("zeit");
+const utils = @import("utils.zig");
/// Select 4 hours representing morning (6am), noon (12pm), evening (6pm), night (12am) in LOCAL time
/// Hours in the hourly forecast are assumed to be all on the same day, in local time
@@ -46,13 +47,6 @@ fn selectHourlyForecasts(all_hours: []const types.HourlyForecast, buf: []?types.
return selected.items;
}
-fn degreeToArrow(deg: f32) []const u8 {
- const normalized = @mod(deg + 22.5, 360.0);
- const idx: usize = @intFromFloat(normalized / 45.0);
- const arrows = [_][]const u8{ "↓", "↙", "←", "↖", "↑", "↗", "→", "↘" };
- return arrows[@min(idx, 7)];
-}
-
pub const Format = enum {
plain_text,
ansi,
@@ -146,7 +140,7 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
.plain_text => {
try w.print("{s} {s}\n", .{ art[0], current.condition });
try w.print("{s} {c}{d:.0}({c}{d:.0}) {s}\n", .{ art[1], 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_speed, wind_unit });
+ try w.print("{s} {s} {d:.0} {s}\n", .{ art[2], utils.degreeToArrow(current.wind_deg), 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";
@@ -163,7 +157,7 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
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 });
+ try w.print("{s} {s} \x1b[38;5;{d}m{d:.0}{s} {s}\n", .{ art[2], utils.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";
@@ -179,7 +173,7 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
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 });
+ try w.print("{s} {s} {d:.0} {s}\n", .{ art[2], utils.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";
@@ -329,7 +323,7 @@ fn renderHourlyCell(w: *std.Io.Writer, hour: types.HourlyForecast, line: usize,
.wind => {
const wind_speed = if (options.use_imperial) hour.windMph() else hour.wind_kph;
const wind_unit = if (options.use_imperial) "mph" else "km/h";
- const arrow = degreeToArrow(hour.wind_deg);
+ const arrow = utils.degreeToArrow(hour.wind_deg);
switch (options.format) {
.ansi => {
const color = windColor(hour.wind_kph);
diff --git a/src/render/Line.zig b/src/render/Line.zig
index 13dda6a..dbb3786 100644
--- a/src/render/Line.zig
+++ b/src/render/Line.zig
@@ -11,68 +11,52 @@ const Format = enum(u3) {
};
pub fn render(writer: *std.Io.Writer, data: types.WeatherData, format: Format, use_imperial: bool) !void {
+ const temp = if (use_imperial) data.current.tempFahrenheit() else data.current.temp_c;
+ const unit = if (use_imperial) "°F" else "°C";
+ const sign: []const u8 = if (temp >= 0) "+" else if (temp < 0) "-" else "";
+ const abs_temp = @abs(temp);
+ const wind = if (use_imperial) data.current.windMph() else data.current.wind_kph;
+ const wind_unit = if (use_imperial) "mph" else "km/h";
+
switch (format) {
.@"1" => {
- const temp = if (use_imperial) data.current.tempFahrenheit() else data.current.temp_c;
- const unit = if (use_imperial) "°F" else "°C";
- try writer.print("{s}: {s} {d:.0}{s}", .{
- data.location,
+ try writer.print("{s} {s}{d:.0}{s}", .{
emoji.getWeatherEmoji(data.current.weather_code),
- temp,
+ sign,
+ abs_temp,
unit,
});
},
.@"2" => {
- const temp = if (use_imperial) data.current.tempFahrenheit() else data.current.temp_c;
- const unit = if (use_imperial) "°F" else "°C";
- const wind = if (use_imperial) data.current.windMph() else data.current.wind_kph;
- const wind_unit = if (use_imperial) "mph" else "km/h";
- try writer.print("{s}: {s} {d:.0}{s} {s}{s}{d:.0}{s}", .{
- data.location,
+ try writer.print("{s} 🌡️{s}{d:.0}{s} 🌬️{s}{d:.0}{s}", .{
emoji.getWeatherEmoji(data.current.weather_code),
- temp,
+ sign,
+ abs_temp,
unit,
- "🌬️",
- utils.degreeToDirection(data.current.wind_deg),
+ utils.degreeToArrow(data.current.wind_deg),
wind,
wind_unit,
});
},
.@"3" => {
- const temp = if (use_imperial) data.current.tempFahrenheit() else data.current.temp_c;
- const unit = if (use_imperial) "°F" else "°C";
- const wind = if (use_imperial) data.current.windMph() else data.current.wind_kph;
- const wind_unit = if (use_imperial) "mph" else "km/h";
- try writer.print("{s}: {s} {d:.0}{s} {s}{s}{d:.0}{s} {s}{d}%%", .{
+ try writer.print("{s}: {s} {s}{d:.0}{s}", .{
data.location,
emoji.getWeatherEmoji(data.current.weather_code),
- temp,
+ sign,
+ abs_temp,
unit,
- "🌬️",
- utils.degreeToDirection(data.current.wind_deg),
- wind,
- wind_unit,
- "💧",
- data.current.humidity,
});
},
.@"4" => {
- const temp = if (use_imperial) data.current.tempFahrenheit() else data.current.temp_c;
- const unit = if (use_imperial) "°F" else "°C";
- const wind = if (use_imperial) data.current.windMph() else data.current.wind_kph;
- const wind_unit = if (use_imperial) "mph" else "km/h";
- try writer.print("{s}: {s} {d:.0}{s} {s}{s}{d:.0}{s} {s}{d}%% {s}", .{
+ try writer.print("{s}: {s} 🌡️{s}{d:.0}{s} 🌬️{s}{d:.0}{s}", .{
data.location,
emoji.getWeatherEmoji(data.current.weather_code),
- temp,
+ sign,
+ abs_temp,
unit,
- "🌬️",
- utils.degreeToDirection(data.current.wind_deg),
+ utils.degreeToArrow(data.current.wind_deg),
wind,
wind_unit,
- "💧",
- data.current.humidity,
- "☀️",
});
},
}
@@ -105,7 +89,7 @@ test "format 1" {
const output = output_buf[0..writer.end];
- try std.testing.expectEqualStrings("London: ☀️ 15°C", output);
+ try std.testing.expectEqualStrings("☀️ +15°C", output);
}
test "format 2 with imperial units" {
@@ -116,7 +100,7 @@ test "format 2 with imperial units" {
const output = output_buf[0..writer.end];
- try std.testing.expectEqualStrings("London: ☀️ 59°F 🌬️N6mph", output);
+ try std.testing.expectEqualStrings("☀️ 🌡️+59°F 🌬️↓6mph", output);
}
test "format 3 with metric units" {
@@ -127,7 +111,7 @@ test "format 3 with metric units" {
const output = output_buf[0..writer.end];
- try std.testing.expectEqualStrings("London: ☀️ 15°C 🌬️N10km/h 💧65%%", output);
+ try std.testing.expectEqualStrings("London: ☀️ +15°C", output);
}
test "format 3 with imperial units" {
@@ -138,7 +122,7 @@ test "format 3 with imperial units" {
const output = output_buf[0..writer.end];
- try std.testing.expectEqualStrings("London: ☀️ 59°F 🌬️N6mph 💧65%%", output);
+ try std.testing.expectEqualStrings("London: ☀️ +59°F", output);
}
test "format 4 with metric units" {
@@ -149,7 +133,7 @@ test "format 4 with metric units" {
const output = output_buf[0..writer.end];
- try std.testing.expectEqualStrings("London: ☀️ 15°C 🌬️N10km/h 💧65%% ☀️", output);
+ try std.testing.expectEqualStrings("London: ☀️ 🌡️+15°C 🌬️↓10km/h", output);
}
test "format 4 with imperial units" {
@@ -160,5 +144,5 @@ test "format 4 with imperial units" {
const output = output_buf[0..writer.end];
- try std.testing.expectEqualStrings("London: ☀️ 59°F 🌬️N6mph 💧65%% ☀️", output);
+ try std.testing.expectEqualStrings("London: ☀️ 🌡️+59°F 🌬️↓6mph", output);
}
diff --git a/src/render/utils.zig b/src/render/utils.zig
index 4df44ad..3398791 100644
--- a/src/render/utils.zig
+++ b/src/render/utils.zig
@@ -7,6 +7,13 @@ pub fn degreeToDirection(deg: f32) []const u8 {
return directions[@min(idx, 7)];
}
+pub fn degreeToArrow(deg: f32) []const u8 {
+ const normalized = @mod(deg + 22.5, 360.0);
+ const idx: usize = @intFromFloat(normalized / 45.0);
+ const arrows = [_][]const u8{ "↓", "↙", "←", "↖", "↑", "↗", "→", "↘" };
+ return arrows[@min(idx, 7)];
+}
+
test "degreeToDirection" {
try std.testing.expectEqualStrings("N", degreeToDirection(0));
try std.testing.expectEqualStrings("NE", degreeToDirection(45));