From a7721ff9594c4d2e1367d7e06870d4e9427675a1 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Thu, 18 Dec 2025 17:03:34 -0800 Subject: [PATCH] ai completed the ansi version --- src/render/ansi.zig | 303 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 298 insertions(+), 5 deletions(-) diff --git a/src/render/ansi.zig b/src/render/ansi.zig index d5aa230..96defb0 100644 --- a/src/render/ansi.zig +++ b/src/render/ansi.zig @@ -18,16 +18,89 @@ pub fn render(allocator: std.mem.Allocator, data: types.WeatherData, options: Re const temp = if (options.use_imperial) data.current.temp_f else data.current.temp_c; const temp_unit = if (options.use_imperial) "°F" else "°C"; + const wind_unit = if (options.use_imperial) "mph" else "km/h"; + const wind_speed = if (options.use_imperial) data.current.wind_kph * 0.621371 else data.current.wind_kph; - try output.writer(allocator).print(" \\ / {s}\n", .{data.current.condition}); - try output.writer(allocator).print(" .-. {d:.1}{s}\n", .{ temp, temp_unit }); - try output.writer(allocator).print(" ― ( ) ― {s} {d:.1} km/h\n", .{ data.current.wind_dir, data.current.wind_kph }); - try output.writer(allocator).print(" `-' Humidity: {d}%\n", .{data.current.humidity}); - try output.writer(allocator).print(" / \\ {d:.1} mm\n\n", .{data.current.precip_mm}); + const art = getWeatherArt(data.current.weather_code); + const w = output.writer(allocator); + + try w.print("{s} {s}\n", .{ art[0], data.current.condition }); + try w.print("{s} {d:.1}{s}\n", .{ art[1], temp, temp_unit }); + try w.print("{s} {s} {d:.1} {s}\n", .{ art[2], data.current.wind_dir, wind_speed, wind_unit }); + try w.print("{s} Humidity: {d}%\n", .{ art[3], data.current.humidity }); + try w.print("{s} {d:.1} mm\n\n", .{ art[4], data.current.precip_mm }); return output.toOwnedSlice(allocator); } +fn getWeatherArt(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", @@ -51,3 +124,223 @@ test "render with imperial units" { try std.testing.expect(std.mem.indexOf(u8, output, "50.0°F") != null); } + +test "clear weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 20.0, + .temp_f = 68.0, + .condition = "Clear", + .weather_code = .clear, + .humidity = 50, + .wind_kph = 10.0, + .wind_dir = "N", + .pressure_mb = 1013.0, + .precip_mm = 0.0, + }, + .forecast = &.{}, + .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); +} + +test "partly cloudy weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 18.0, + .temp_f = 64.0, + .condition = "Partly cloudy", + .weather_code = .clouds_few, + .humidity = 55, + .wind_kph = 12.0, + .wind_dir = "NE", + .pressure_mb = 1013.0, + .precip_mm = 0.0, + }, + .forecast = &.{}, + .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); +} + +test "cloudy weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 15.0, + .temp_f = 59.0, + .condition = "Cloudy", + .weather_code = .clouds_overcast, + .humidity = 70, + .wind_kph = 15.0, + .wind_dir = "E", + .pressure_mb = 1010.0, + .precip_mm = 0.0, + }, + .forecast = &.{}, + .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); +} + +test "rain weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 12.0, + .temp_f = 54.0, + .condition = "Rain", + .weather_code = .rain_moderate, + .humidity = 85, + .wind_kph = 20.0, + .wind_dir = "SE", + .pressure_mb = 1005.0, + .precip_mm = 5.0, + }, + .forecast = &.{}, + .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); +} + +test "thunderstorm weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 14.0, + .temp_f = 57.0, + .condition = "Thunderstorm", + .weather_code = .thunderstorm, + .humidity = 90, + .wind_kph = 30.0, + .wind_dir = "S", + .pressure_mb = 1000.0, + .precip_mm = 10.0, + }, + .forecast = &.{}, + .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); +} + +test "snow weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = -2.0, + .temp_f = 28.0, + .condition = "Snow", + .weather_code = .snow, + .humidity = 80, + .wind_kph = 18.0, + .wind_dir = "SW", + .pressure_mb = 1008.0, + .precip_mm = 3.0, + }, + .forecast = &.{}, + .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); +} + +test "sleet weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 0.0, + .temp_f = 32.0, + .condition = "Sleet", + .weather_code = .sleet, + .humidity = 75, + .wind_kph = 22.0, + .wind_dir = "W", + .pressure_mb = 1007.0, + .precip_mm = 2.0, + }, + .forecast = &.{}, + .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); +} + +test "fog weather art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 8.0, + .temp_f = 46.0, + .condition = "Fog", + .weather_code = .fog, + .humidity = 95, + .wind_kph = 5.0, + .wind_dir = "NW", + .pressure_mb = 1012.0, + .precip_mm = 0.0, + }, + .forecast = &.{}, + .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); +} + +test "unknown weather code art" { + const data = types.WeatherData{ + .location = "Test", + .current = .{ + .temp_c = 16.0, + .temp_f = 61.0, + .condition = "Unknown", + .weather_code = @enumFromInt(999), + .humidity = 60, + .wind_kph = 10.0, + .wind_dir = "N", + .pressure_mb = 1013.0, + .precip_mm = 0.0, + }, + .forecast = &.{}, + .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); +}