ai stuff to fix colors, etc
This commit is contained in:
parent
662e0c5e33
commit
9c7902aca8
2 changed files with 173 additions and 9 deletions
|
|
@ -21,18 +21,65 @@ pub fn render(allocator: std.mem.Allocator, data: types.WeatherData, options: Re
|
|||
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;
|
||||
|
||||
// Dynamic colors based on temperature and wind speed
|
||||
const temp_color_code = tempColor(data.current.temp_c);
|
||||
const wind_color_code = windColor(data.current.wind_kph);
|
||||
const rain_color = "\x1b[38;5;111m"; // light blue
|
||||
const cloud_color = "\x1b[38;5;250m"; // gray
|
||||
const reset = "\x1b[0m";
|
||||
|
||||
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 });
|
||||
try w.print("{s}{s}{s} {s}\n", .{ cloud_color, art[0], reset, data.current.condition });
|
||||
try w.print("{s}{s}{s} \x1b[38;5;{d}m{d:.1}{s}{s}\n", .{ cloud_color, art[1], reset, temp_color_code, temp, temp_unit, reset });
|
||||
try w.print("{s}{s}{s} {s} \x1b[38;5;{d}m{d:.1}{s} {s}\n", .{ cloud_color, art[2], reset, data.current.wind_dir, wind_color_code, wind_speed, reset, wind_unit });
|
||||
try w.print("{s}{s}{s} Humidity: {d}%\n", .{ cloud_color, art[3], reset, data.current.humidity });
|
||||
try w.print("{s}{s}{s} {s}{d:.1}{s} mm\n\n", .{ rain_color, art[4], reset, rain_color, data.current.precip_mm, reset });
|
||||
|
||||
return output.toOwnedSlice(allocator);
|
||||
}
|
||||
|
||||
fn tempColor(temp_c: f32) u8 {
|
||||
const temp: i32 = @intFromFloat(@round(temp_c));
|
||||
return switch (temp) {
|
||||
-15, -14, -13 => 27,
|
||||
-12, -11, -10 => 33,
|
||||
-9, -8, -7 => 39,
|
||||
-6, -5, -4 => 45,
|
||||
-3, -2, -1 => 51,
|
||||
0, 1 => 50,
|
||||
2, 3 => 49,
|
||||
4, 5 => 48,
|
||||
6, 7 => 47,
|
||||
8, 9 => 46,
|
||||
10, 11, 12 => 82,
|
||||
13, 14, 15 => 118,
|
||||
16, 17, 18 => 154,
|
||||
19, 20, 21 => 190,
|
||||
22, 23, 24 => 226,
|
||||
25, 26, 27 => 220,
|
||||
28, 29, 30 => 214,
|
||||
31, 32, 33 => 208,
|
||||
34, 35, 36 => 202,
|
||||
else => if (temp > 36) 196 else 21,
|
||||
};
|
||||
}
|
||||
|
||||
fn windColor(wind_kph: f32) u8 {
|
||||
const wind: i32 = @intFromFloat(@round(wind_kph));
|
||||
if (wind <= 3) return 241;
|
||||
if (wind <= 6) return 242;
|
||||
if (wind <= 9) return 243;
|
||||
if (wind <= 12) return 246;
|
||||
if (wind <= 15) return 250;
|
||||
if (wind <= 19) return 253;
|
||||
if (wind <= 23) return 214;
|
||||
if (wind <= 27) return 208;
|
||||
if (wind <= 31) return 202;
|
||||
return 196;
|
||||
}
|
||||
|
||||
fn getWeatherArt(code: types.WeatherCode) [5][]const u8 {
|
||||
return switch (@intFromEnum(code)) {
|
||||
800 => .{ // Clear
|
||||
|
|
@ -123,6 +170,8 @@ test "render with imperial units" {
|
|||
defer std.testing.allocator.free(output);
|
||||
|
||||
try std.testing.expect(std.mem.indexOf(u8, output, "50.0°F") != null);
|
||||
// 10°C should be color 82
|
||||
try std.testing.expect(std.mem.indexOf(u8, output, "\x1b[38;5;82m") != null);
|
||||
}
|
||||
|
||||
test "clear weather art" {
|
||||
|
|
@ -344,3 +393,108 @@ test "unknown weather code art" {
|
|||
try std.testing.expect(std.mem.indexOf(u8, output, "?") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, output, "¯\\_(ツ)_/¯") != null);
|
||||
}
|
||||
|
||||
test "temperature matches between ansi and custom format" {
|
||||
const custom = @import("custom.zig");
|
||||
|
||||
const data = types.WeatherData{
|
||||
.location = "PDX",
|
||||
.current = .{
|
||||
.temp_c = 13.1,
|
||||
.temp_f = 55.6,
|
||||
.condition = "Clear",
|
||||
.weather_code = .clear,
|
||||
.humidity = 60,
|
||||
.wind_kph = 10.0,
|
||||
.wind_dir = "N",
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
};
|
||||
|
||||
const ansi_output = try render(std.testing.allocator, data, .{ .use_imperial = true });
|
||||
defer std.testing.allocator.free(ansi_output);
|
||||
|
||||
const custom_output = try custom.render(std.testing.allocator, data, "%t", true);
|
||||
defer std.testing.allocator.free(custom_output);
|
||||
|
||||
// Both should show 55.6°F
|
||||
try std.testing.expect(std.mem.indexOf(u8, ansi_output, "55.6°F") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, custom_output, "55.6°F") != null);
|
||||
}
|
||||
|
||||
test "tempColor returns correct colors for temperature ranges" {
|
||||
// Very cold
|
||||
try std.testing.expectEqual(@as(u8, 27), tempColor(-15));
|
||||
try std.testing.expectEqual(@as(u8, 27), tempColor(-13));
|
||||
try std.testing.expectEqual(@as(u8, 33), tempColor(-12));
|
||||
try std.testing.expectEqual(@as(u8, 33), tempColor(-10));
|
||||
|
||||
// Cold
|
||||
try std.testing.expectEqual(@as(u8, 39), tempColor(-9));
|
||||
try std.testing.expectEqual(@as(u8, 45), tempColor(-6));
|
||||
try std.testing.expectEqual(@as(u8, 51), tempColor(-3));
|
||||
|
||||
// Cool
|
||||
try std.testing.expectEqual(@as(u8, 50), tempColor(0));
|
||||
try std.testing.expectEqual(@as(u8, 49), tempColor(2));
|
||||
try std.testing.expectEqual(@as(u8, 48), tempColor(4));
|
||||
try std.testing.expectEqual(@as(u8, 46), tempColor(8));
|
||||
|
||||
// Mild
|
||||
try std.testing.expectEqual(@as(u8, 82), tempColor(10));
|
||||
try std.testing.expectEqual(@as(u8, 118), tempColor(13));
|
||||
try std.testing.expectEqual(@as(u8, 118), tempColor(15));
|
||||
|
||||
// Warm
|
||||
try std.testing.expectEqual(@as(u8, 154), tempColor(16));
|
||||
try std.testing.expectEqual(@as(u8, 190), tempColor(20));
|
||||
try std.testing.expectEqual(@as(u8, 226), tempColor(23));
|
||||
try std.testing.expectEqual(@as(u8, 220), tempColor(26));
|
||||
|
||||
// Hot
|
||||
try std.testing.expectEqual(@as(u8, 214), tempColor(29));
|
||||
try std.testing.expectEqual(@as(u8, 208), tempColor(32));
|
||||
try std.testing.expectEqual(@as(u8, 202), tempColor(35));
|
||||
|
||||
// Very hot
|
||||
try std.testing.expectEqual(@as(u8, 196), tempColor(37));
|
||||
try std.testing.expectEqual(@as(u8, 196), tempColor(50));
|
||||
|
||||
// Very cold (below range)
|
||||
try std.testing.expectEqual(@as(u8, 21), tempColor(-20));
|
||||
}
|
||||
|
||||
test "windColor returns correct colors for wind speed ranges" {
|
||||
// Calm
|
||||
try std.testing.expectEqual(@as(u8, 241), windColor(0));
|
||||
try std.testing.expectEqual(@as(u8, 241), windColor(3));
|
||||
|
||||
// Light breeze
|
||||
try std.testing.expectEqual(@as(u8, 242), windColor(4));
|
||||
try std.testing.expectEqual(@as(u8, 242), windColor(6));
|
||||
try std.testing.expectEqual(@as(u8, 243), windColor(7));
|
||||
try std.testing.expectEqual(@as(u8, 243), windColor(9));
|
||||
|
||||
// Moderate
|
||||
try std.testing.expectEqual(@as(u8, 246), windColor(10));
|
||||
try std.testing.expectEqual(@as(u8, 246), windColor(12));
|
||||
try std.testing.expectEqual(@as(u8, 250), windColor(13));
|
||||
try std.testing.expectEqual(@as(u8, 250), windColor(15));
|
||||
try std.testing.expectEqual(@as(u8, 253), windColor(16));
|
||||
try std.testing.expectEqual(@as(u8, 253), windColor(19));
|
||||
|
||||
// Fresh
|
||||
try std.testing.expectEqual(@as(u8, 214), windColor(20));
|
||||
try std.testing.expectEqual(@as(u8, 214), windColor(23));
|
||||
try std.testing.expectEqual(@as(u8, 208), windColor(24));
|
||||
try std.testing.expectEqual(@as(u8, 208), windColor(27));
|
||||
|
||||
// Strong
|
||||
try std.testing.expectEqual(@as(u8, 202), windColor(28));
|
||||
try std.testing.expectEqual(@as(u8, 202), windColor(31));
|
||||
try std.testing.expectEqual(@as(u8, 196), windColor(32));
|
||||
try std.testing.expectEqual(@as(u8, 196), windColor(50));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,12 +29,22 @@ pub fn render(allocator: std.mem.Allocator, weather: types.WeatherData, format:
|
|||
't' => {
|
||||
const temp = if (use_imperial) weather.current.temp_f else weather.current.temp_c;
|
||||
const unit = if (use_imperial) "°F" else "°C";
|
||||
try writer.print("{d:.0}{s}", .{ temp, unit });
|
||||
const sign: u8 = if (temp >= 0) '+' else 0;
|
||||
if (sign != 0) {
|
||||
try writer.print("{c}{d:.1}{s}", .{ sign, temp, unit });
|
||||
} else {
|
||||
try writer.print("{d:.1}{s}", .{ temp, unit });
|
||||
}
|
||||
},
|
||||
'f' => {
|
||||
const temp = if (use_imperial) weather.current.temp_f else weather.current.temp_c;
|
||||
const unit = if (use_imperial) "°F" else "°C";
|
||||
try writer.print("{d:.0}{s}", .{ temp, unit });
|
||||
const sign: u8 = if (temp >= 0) '+' else 0;
|
||||
if (sign != 0) {
|
||||
try writer.print("{c}{d:.1}{s}", .{ sign, temp, unit });
|
||||
} else {
|
||||
try writer.print("{d:.1}{s}", .{ temp, unit });
|
||||
}
|
||||
},
|
||||
'w' => {
|
||||
const wind = if (use_imperial) weather.current.wind_kph * 0.621371 else weather.current.wind_kph;
|
||||
|
|
@ -100,7 +110,7 @@ test "render custom format with location and temp" {
|
|||
defer allocator.free(output);
|
||||
|
||||
try std.testing.expect(std.mem.indexOf(u8, output, "London") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, output, "7°C") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, output, "+7.0°C") != null);
|
||||
}
|
||||
|
||||
test "render custom format with newline" {
|
||||
|
|
@ -179,7 +189,7 @@ test "render custom format with imperial units" {
|
|||
const output = try render(allocator, weather, "%t %w %p", true);
|
||||
defer allocator.free(output);
|
||||
|
||||
try std.testing.expect(std.mem.indexOf(u8, output, "50°F") != null);
|
||||
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, "in") != null);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue