get one line output matching wttr.in
This commit is contained in:
parent
115af96c8a
commit
59ec75dbf6
4 changed files with 42 additions and 57 deletions
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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} <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 });
|
||||
try w.print("{s} {s} <span style=\"color:{s}\">{d:.0}</span> {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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue