visibility handling
This commit is contained in:
parent
52a5bf2543
commit
9d3667b8ec
7 changed files with 70 additions and 18 deletions
|
|
@ -91,6 +91,7 @@ test "render custom format with location and temp" {
|
|||
.wind_deg = 22.5,
|
||||
.pressure_mb = 1019.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &[_]types.ForecastDay{},
|
||||
.allocator = allocator,
|
||||
|
|
@ -118,6 +119,7 @@ test "render custom format with newline" {
|
|||
.wind_deg = 90.0,
|
||||
.pressure_mb = 1020.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &[_]types.ForecastDay{},
|
||||
.allocator = allocator,
|
||||
|
|
@ -144,6 +146,7 @@ test "render custom format with humidity and pressure" {
|
|||
.wind_deg = 270.0,
|
||||
.pressure_mb = 1012.0,
|
||||
.precip_mm = 0.2,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &[_]types.ForecastDay{},
|
||||
.allocator = allocator,
|
||||
|
|
@ -171,6 +174,7 @@ test "render custom format with imperial units" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 2.5,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &[_]types.ForecastDay{},
|
||||
.allocator = allocator,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
const std = @import("std");
|
||||
const types = @import("../weather/types.zig");
|
||||
const utils = @import("utils.zig");
|
||||
|
||||
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,
|
||||
|
|
@ -45,7 +51,6 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
|
|||
const wind_speed = if (options.use_imperial) current.wind_kph * 0.621371 else current.wind_kph;
|
||||
const precip_unit = if (options.use_imperial) "in" else "mm";
|
||||
const precip = if (options.use_imperial) current.precip_mm * 0.0393701 else current.precip_mm;
|
||||
const visibility = if (options.use_imperial) "6 mi" else "10 km";
|
||||
|
||||
const art = getWeatherArt(current.weather_code);
|
||||
const sign: u8 = if (temp >= 0) '+' else '-';
|
||||
|
|
@ -56,8 +61,14 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
|
|||
if (options.format == .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], utils.degreeToDirection(current.wind_deg), wind_speed, wind_unit });
|
||||
try w.print("{s} {s}\n", .{ art[3], visibility });
|
||||
try w.print("{s} {s} {d:.0} {s}\n", .{ art[2], degreeToArrow(current.wind_deg), wind_speed, wind_unit });
|
||||
if (current.visibility_km) |vis_km| {
|
||||
const visibility = if (options.use_imperial) vis_km * 0.621371 else vis_km;
|
||||
const vis_unit = if (options.use_imperial) "mi" else "km";
|
||||
try w.print("{s} {d:.0} {s}\n", .{ art[3], visibility, vis_unit });
|
||||
} else {
|
||||
try w.print("{s}\n", .{std.mem.trimRight(u8, art[3], " ")});
|
||||
}
|
||||
try w.print("{s} {d:.1} {s}\n", .{ art[4], precip, precip_unit });
|
||||
} else {
|
||||
const temp_color_code = tempColor(current.temp_c);
|
||||
|
|
@ -67,8 +78,14 @@ fn renderCurrent(w: *std.Io.Writer, current: types.CurrentCondition, options: Re
|
|||
|
||||
try w.print("{s}{s}{s} {s}\n", .{ cloud_color, art[0], reset, current.condition });
|
||||
try w.print("{s}{s}{s} \x1b[38;5;{d}m{c}{d:.0}({c}{d:.0}){s} {s}\n", .{ cloud_color, art[1], reset, temp_color_code, sign, abs_temp, fl_sign, abs_fl, reset, temp_unit });
|
||||
try w.print("{s}{s}{s} {s} \x1b[38;5;{d}m{d:.0}{s} {s}\n", .{ cloud_color, art[2], reset, utils.degreeToDirection(current.wind_deg), wind_color_code, wind_speed, reset, wind_unit });
|
||||
try w.print("{s}{s}{s} {s}\n", .{ cloud_color, art[3], reset, visibility });
|
||||
try w.print("{s}{s}{s} {s} \x1b[38;5;{d}m{d:.0}{s} {s}\n", .{ cloud_color, art[2], reset, degreeToArrow(current.wind_deg), wind_color_code, wind_speed, reset, wind_unit });
|
||||
if (current.visibility_km) |vis_km| {
|
||||
const visibility = if (options.use_imperial) vis_km * 0.621371 else vis_km;
|
||||
const vis_unit = if (options.use_imperial) "mi" else "km";
|
||||
try w.print("{s}{s}{s} {d:.0} {s}\n", .{ cloud_color, art[3], reset, visibility, vis_unit });
|
||||
} else {
|
||||
try w.print("{s}{s}{s}\n", .{ cloud_color, std.mem.trimRight(u8, art[3], " "), reset });
|
||||
}
|
||||
try w.print("{s}{s}{s} {d:.1} {s}\n", .{ cloud_color, art[4], reset, precip, precip_unit });
|
||||
}
|
||||
}
|
||||
|
|
@ -155,14 +172,16 @@ fn renderHourlyCell(w: *std.Io.Writer, hour: types.HourlyForecast, line: usize,
|
|||
.wind => {
|
||||
const wind_speed = if (options.use_imperial) hour.wind_kph * 0.621371192237 else hour.wind_kph;
|
||||
const wind_unit = if (options.use_imperial) "mph" else "km/h";
|
||||
// Wind direction is two bytes, so we need to subtract one
|
||||
// Somehow the actual answer here is two, though?
|
||||
try cell_writer.print("↑ {d:.0} {s}", .{ wind_speed, wind_unit });
|
||||
display_width_byte_length_offset = 2;
|
||||
const arrow = degreeToArrow(hour.wind_deg);
|
||||
try cell_writer.print("{s} {d:.0} {s}", .{ arrow, wind_speed, wind_unit });
|
||||
display_width_byte_length_offset = arrow.len - 1;
|
||||
},
|
||||
.visibility => {
|
||||
const visibility = if (options.use_imperial) "6 mi" else "10 km";
|
||||
try cell_writer.print("{s}", .{visibility});
|
||||
if (hour.visibility_km) |vis_km| {
|
||||
const visibility = if (options.use_imperial) vis_km * 0.621371 else vis_km;
|
||||
const vis_unit = if (options.use_imperial) "mi" else "km";
|
||||
try cell_writer.print("{d:.0} {s}", .{ visibility, vis_unit });
|
||||
}
|
||||
},
|
||||
.precipitation => {
|
||||
const precip = if (options.use_imperial) hour.precip_mm * 0.0393701 else hour.precip_mm;
|
||||
|
|
@ -331,6 +350,7 @@ test "render with imperial units" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -358,6 +378,7 @@ test "clear weather art" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -383,6 +404,7 @@ test "partly cloudy weather art" {
|
|||
.wind_deg = 45.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -408,6 +430,7 @@ test "cloudy weather art" {
|
|||
.wind_deg = 90.0,
|
||||
.pressure_mb = 1010.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -433,6 +456,7 @@ test "rain weather art" {
|
|||
.wind_deg = 135.0,
|
||||
.pressure_mb = 1005.0,
|
||||
.precip_mm = 5.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -457,6 +481,7 @@ test "thunderstorm weather art" {
|
|||
.wind_deg = 180.0,
|
||||
.pressure_mb = 1000.0,
|
||||
.precip_mm = 10.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -481,6 +506,7 @@ test "snow weather art" {
|
|||
.wind_deg = 225.0,
|
||||
.pressure_mb = 1008.0,
|
||||
.precip_mm = 3.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -505,6 +531,7 @@ test "sleet weather art" {
|
|||
.wind_deg = 270.0,
|
||||
.pressure_mb = 1007.0,
|
||||
.precip_mm = 2.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -529,6 +556,7 @@ test "fog weather art" {
|
|||
.wind_deg = 315.0,
|
||||
.pressure_mb = 1012.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -553,6 +581,7 @@ test "unknown weather code art" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -580,6 +609,7 @@ test "temperature matches between ansi and custom format" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -686,8 +716,8 @@ test "plain text format - MetNo real data" {
|
|||
\\
|
||||
\\ .-. Light rain
|
||||
\\ ( ). +7(+7) °C
|
||||
\\ (___(__) E 6 km/h
|
||||
\\ ʻ ʻ ʻ ʻ 10 km
|
||||
\\ (___(__) ← 6 km/h
|
||||
\\ ʻ ʻ ʻ ʻ
|
||||
\\ ʻ ʻ ʻ ʻ 0.0 mm
|
||||
\\
|
||||
\\
|
||||
|
|
@ -703,8 +733,8 @@ test "plain text format - MetNo real data" {
|
|||
\\├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
|
||||
\\│ .-. Rain │ Cloudy │ .-. Heavy rain │ \ / Partly cloudy │
|
||||
\\│ ( ). +7(+7) °C │ .--. +6(+6) °C │ ( ). +7(+7) °C │ _ /"".-. +8(+8) °C │
|
||||
\\│ (___(__) ↑ 5 km/h │ .-( ). ↑ 9 km/h │ (___(__) ↑ 14 km/h │ \_( ). ↑ 12 km/h │
|
||||
\\│ ʻ ʻ ʻ ʻ 10 km │ (___.__)__) 10 km │ ʻ ʻ ʻ ʻ 10 km │ /(___(__) 10 km │
|
||||
\\│ (___(__) ↖ 5 km/h │ .-( ). ↓ 9 km/h │ (___(__) ↖ 14 km/h │ \_( ). ↑ 12 km/h │
|
||||
\\│ ʻ ʻ ʻ ʻ │ (___.__)__) │ ʻ ʻ ʻ ʻ │ /(___(__) │
|
||||
\\│ ʻ ʻ ʻ ʻ 0.3 mm | 0% │ 0.0 mm | 0% │ ʻ ʻ ʻ ʻ 1.2 mm | 0% │ 0.0 mm | 0% │
|
||||
\\└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
|
||||
\\ ┌─────────────┐
|
||||
|
|
@ -713,8 +743,8 @@ test "plain text format - MetNo real data" {
|
|||
\\├──────────────────────────────┼──────────────────────────────┼──────────────────────────────┼──────────────────────────────┤
|
||||
\\│ Cloudy │ Cloudy │ Cloudy │ .-. Light rain │
|
||||
\\│ .--. +10(+10) °C │ .--. +8(+8) °C │ .--. +10(+10) °C │ ( ). +9(+9) °C │
|
||||
\\│ .-( ). ↑ 7 km/h │ .-( ). ↑ 14 km/h │ .-( ). ↑ 31 km/h │ (___(__) ↑ 24 km/h │
|
||||
\\│ (___.__)__) 10 km │ (___.__)__) 10 km │ (___.__)__) 10 km │ ʻ ʻ ʻ ʻ 10 km │
|
||||
\\│ .-( ). ↙ 7 km/h │ .-( ). ↑ 14 km/h │ .-( ). ↑ 31 km/h │ (___(__) ↑ 24 km/h │
|
||||
\\│ (___.__)__) │ (___.__)__) │ (___.__)__) │ ʻ ʻ ʻ ʻ │
|
||||
\\│ 0.0 mm | 0% │ 0.0 mm | 0% │ 0.0 mm | 0% │ ʻ ʻ ʻ ʻ 0.2 mm | 0% │
|
||||
\\└──────────────────────────────┴──────────────────────────────┴──────────────────────────────┴──────────────────────────────┘
|
||||
\\
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ test "render json format" {
|
|||
.wind_deg = 225.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &[_]types.ForecastDay{},
|
||||
.allocator = allocator,
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ test "format 1" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -155,6 +156,7 @@ test "custom format" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
@ -179,6 +181,7 @@ test "format 2 with imperial units" {
|
|||
.wind_deg = 135.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &.{},
|
||||
.allocator = std.testing.allocator,
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ test "render v2 format" {
|
|||
.wind_deg = 315.0,
|
||||
.pressure_mb = 1015.0,
|
||||
.precip_mm = 0.5,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &[_]types.ForecastDay{},
|
||||
.allocator = allocator,
|
||||
|
|
@ -110,6 +111,7 @@ test "render v2 format with imperial units" {
|
|||
.wind_deg = 0.0,
|
||||
.pressure_mb = 1013.0,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = &[_]types.ForecastDay{},
|
||||
.allocator = allocator,
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ fn parseMetNoResponse(allocator: std.mem.Allocator, coords: Coordinates, json: s
|
|||
.wind_deg = wind_deg,
|
||||
.pressure_mb = pressure_mb,
|
||||
.precip_mm = 0.0,
|
||||
.visibility_km = null,
|
||||
},
|
||||
.forecast = forecast,
|
||||
.allocator = allocator,
|
||||
|
|
@ -244,6 +245,10 @@ fn parseForecastDays(allocator: std.mem.Allocator, timeseries: []std.json.Value)
|
|||
const temp: f32 = @floatCast(details_obj.object.get("air_temperature").?.float);
|
||||
const wind_ms = details_obj.object.get("wind_speed") orelse continue;
|
||||
const wind_kph: f32 = @floatCast(wind_ms.float * 3.6);
|
||||
const wind_deg: f32 = if (details_obj.object.get("wind_from_direction")) |deg|
|
||||
@floatCast(deg.float)
|
||||
else
|
||||
0.0;
|
||||
|
||||
if (current_date == null or !std.mem.eql(u8, current_date.?, date)) {
|
||||
// Save previous day if exists
|
||||
|
|
@ -330,7 +335,9 @@ fn parseForecastDays(allocator: std.mem.Allocator, timeseries: []std.json.Value)
|
|||
.condition = try allocator.dupe(u8, symbolCodeToCondition(symbol_code)),
|
||||
.weather_code = symbolCodeToWeatherCode(symbol_code),
|
||||
.wind_kph = wind_kph,
|
||||
.wind_deg = wind_deg,
|
||||
.precip_mm = precip,
|
||||
.visibility_km = null,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -353,7 +360,9 @@ fn parseForecastDays(allocator: std.mem.Allocator, timeseries: []std.json.Value)
|
|||
.condition = try allocator.dupe(u8, symbolCodeToCondition(symbol_code)),
|
||||
.weather_code = symbolCodeToWeatherCode(symbol_code),
|
||||
.wind_kph = wind_kph,
|
||||
.wind_deg = wind_deg,
|
||||
.precip_mm = precip,
|
||||
.visibility_km = null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ pub const CurrentCondition = struct {
|
|||
wind_deg: f32,
|
||||
pressure_mb: f32,
|
||||
precip_mm: f32,
|
||||
visibility_km: ?f32,
|
||||
|
||||
pub fn tempFahrenheit(self: CurrentCondition) f32 {
|
||||
return celsiusToFahrenheit(self.temp_c);
|
||||
|
|
@ -148,5 +149,7 @@ pub const HourlyForecast = struct {
|
|||
condition: []const u8,
|
||||
weather_code: WeatherCode,
|
||||
wind_kph: f32,
|
||||
wind_deg: f32,
|
||||
precip_mm: f32,
|
||||
visibility_km: ?f32,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue