wttr/src/render/V2.zig

130 lines
4.7 KiB
Zig

const std = @import("std");
const types = @import("../weather/types.zig");
const utils = @import("utils.zig");
pub fn render(writer: *std.Io.Writer, weather: types.WeatherData, use_imperial: bool) !void {
// Header with location
try writer.print("Weather report: {s}\n\n", .{weather.locationDisplayName()});
// Current conditions
try writer.print(" Current conditions\n", .{});
try writer.print(" {s}\n", .{weather.current.condition});
try writer.writeAll(" 🌡️ ");
if (use_imperial) {
try writer.print("{d:.1}°F\n", .{weather.current.tempFahrenheit()});
} else {
try writer.print("{d:.1}°C ({d:.1}°F)\n", .{ weather.current.temp_c, weather.current.tempFahrenheit() });
}
try writer.writeAll(" 💧 ");
try writer.print("{d}%\n", .{weather.current.humidity});
try writer.writeAll(" 🌬️ ");
if (use_imperial) {
const wind_mph = weather.current.windMph();
try writer.print("{d:.1} mph {s}\n", .{ wind_mph, utils.degreeToDirection(weather.current.wind_deg) });
} else {
try writer.print("{d:.1} km/h {s}\n", .{ weather.current.wind_kph, utils.degreeToDirection(weather.current.wind_deg) });
}
try writer.writeAll(" 🔽 ");
if (use_imperial) {
const pressure_inhg = weather.current.pressure_mb * 0.02953;
try writer.print("{d:.2} inHg\n", .{pressure_inhg});
} else {
try writer.print("{d:.1} hPa\n", .{weather.current.pressure_mb});
}
try writer.writeAll(" 💦 ");
if (use_imperial) {
const precip_in = weather.current.precip_mm * 0.0393701;
try writer.print("{d:.2} in\n\n", .{precip_in});
} else {
try writer.print("{d:.1} mm\n\n", .{weather.current.precip_mm});
}
// Forecast
if (weather.forecast.len > 0) {
try writer.print(" Forecast\n", .{});
for (weather.forecast) |day| {
try writer.print(" {}-{:0>2}-{:0>2}: {s}\n", .{ day.date.year, @intFromEnum(day.date.month), day.date.day, day.condition });
try writer.writeAll("");
if (use_imperial) {
try writer.print("{d:.1}°F ", .{day.maxTempFahrenheit()});
} else {
try writer.print("{d:.1}°C ", .{day.max_temp_c});
}
try writer.writeAll("");
if (use_imperial) {
try writer.print("{d:.1}°F\n", .{day.minTempFahrenheit()});
} else {
try writer.print("{d:.1}°C\n", .{day.min_temp_c});
}
}
}
}
test "render v2 format" {
const allocator = std.testing.allocator;
const weather = types.WeatherData{
.location = "Munich",
.coords = .{ .latitude = 0, .longitude = 0 },
.current = .{
.temp_c = 12.0,
.feels_like_c = 12.0,
.condition = "Overcast",
.weather_code = .clouds_overcast,
.humidity = 80,
.wind_kph = 15.0,
.wind_deg = 315.0,
.pressure_mb = 1015.0,
.precip_mm = 0.5,
.visibility_km = null,
},
.forecast = &[_]types.ForecastDay{},
.allocator = allocator,
};
var output_buf: [2048]u8 = undefined;
var writer = std.Io.Writer.fixed(&output_buf);
try render(&writer, weather, false);
const output = output_buf[0..writer.end];
try std.testing.expect(output.len > 0);
try std.testing.expect(std.mem.indexOf(u8, output, "Munich") != null);
try std.testing.expect(std.mem.indexOf(u8, output, "Current conditions") != null);
try std.testing.expect(std.mem.indexOf(u8, output, "12.0°C") != null);
}
test "render v2 format with imperial units" {
const allocator = std.testing.allocator;
const weather = types.WeatherData{
.location = "Boston",
.coords = .{ .latitude = 0, .longitude = 0 },
.current = .{
.temp_c = 10.0,
.feels_like_c = 10.0,
.condition = "Clear",
.weather_code = .clear,
.humidity = 65,
.wind_kph = 16.0,
.wind_deg = 0.0,
.pressure_mb = 1013.0,
.precip_mm = 0.0,
.visibility_km = null,
},
.forecast = &[_]types.ForecastDay{},
.allocator = allocator,
};
var output_buf: [2048]u8 = undefined;
var writer = std.Io.Writer.fixed(&output_buf);
try render(&writer, weather, true);
const output = output_buf[0..writer.end];
try std.testing.expect(std.mem.indexOf(u8, output, "50.0°F") != null);
try std.testing.expect(std.mem.indexOf(u8, output, "mph") != null);
try std.testing.expect(std.mem.indexOf(u8, output, "inHg") != null);
}