Init
This commit is contained in:
commit
184645ba63
73 changed files with 4983 additions and 0 deletions
131
src/eink_feed_render/apps/Departures/root.zig
Normal file
131
src/eink_feed_render/apps/Departures/root.zig
Normal file
|
@ -0,0 +1,131 @@
|
|||
const std = @import("std");
|
||||
const temp = @import("temp");
|
||||
const zdt = @import("zdt");
|
||||
|
||||
const Dimensions = @import("../../Dimensions.zig");
|
||||
const renderer = @import("../../renderer.zig");
|
||||
|
||||
pub const efa = @import("efa.zig");
|
||||
|
||||
const template = @import("template/root.zig");
|
||||
|
||||
const Self = @This();
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
dimensions: Dimensions,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, dimensions: Dimensions) Self {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.dimensions = dimensions,
|
||||
};
|
||||
}
|
||||
|
||||
pub const RenderOptions = struct {
|
||||
now: *const zdt.Datetime,
|
||||
tz: *const zdt.Timezone,
|
||||
max_items: usize,
|
||||
show_operator: bool,
|
||||
};
|
||||
|
||||
pub fn render(self: *const Self, efa_dm_resp: *const efa.DmResponse, options: RenderOptions) ![]const u8 {
|
||||
const now_local = try options.now.tzConvert(.{ .tz = options.tz });
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(self.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const departures = try arena.allocator().alloc(template.Departure, efa_dm_resp.stopEvents.len);
|
||||
var dep_i: usize = 0;
|
||||
for (efa_dm_resp.stopEvents) |dep| {
|
||||
const dp_timetable = try zdt.Datetime.fromISO8601(dep.departureTimeBaseTimetable);
|
||||
const dp_timetable_local = try dp_timetable.tzConvert(.{ .tz = options.tz });
|
||||
|
||||
const dp_planned = try zdt.Datetime.fromISO8601(
|
||||
dep.departureTimeEstimated orelse dep.departureTimePlanned,
|
||||
);
|
||||
const dp_planned_local = try dp_planned.tzConvert(.{ .tz = options.tz });
|
||||
|
||||
const diff_min: i32 = @intFromFloat(dp_planned_local.diff(dp_timetable_local).totalMinutes());
|
||||
const on_time: ?u32 = if (diff_min < 0) @abs(diff_min) else null;
|
||||
const delayed: ?u32 = if (diff_min > 0) @abs(diff_min) else null;
|
||||
|
||||
const date: ?[]const u8 = if (dp_planned_local.dayOfYear() != now_local.dayOfYear())
|
||||
try std.fmt.allocPrint(arena.allocator(), "{d}.{d}.{d}", .{
|
||||
dp_planned_local.day,
|
||||
dp_planned_local.month,
|
||||
dp_planned_local.year,
|
||||
})
|
||||
else
|
||||
null;
|
||||
|
||||
var infos: ?[]const []const u8 = null;
|
||||
if (dep.hints) |hints| {
|
||||
const arr = try arena.allocator().alloc([]const u8, hints.len + 1);
|
||||
var i: usize = 0;
|
||||
for (hints) |hint| {
|
||||
if (std.mem.eql(u8, hint.type, "Timetable"))
|
||||
continue;
|
||||
|
||||
arr[i] = hint.content;
|
||||
i += 1;
|
||||
}
|
||||
|
||||
infos = arr[0..i];
|
||||
}
|
||||
|
||||
departures[dep_i] = template.Departure{
|
||||
.time = try std.fmt.allocPrint(
|
||||
arena.allocator(),
|
||||
"{d}:{d:0>2}",
|
||||
.{ dp_timetable_local.hour, dp_timetable_local.minute },
|
||||
),
|
||||
.time_unix = dp_timetable_local.toUnix(.second),
|
||||
.line = dep.transportation.name,
|
||||
.transportation_product_class = dep.transportation.product.class,
|
||||
.operator = if (dep.transportation.operator) |op| op.name else null,
|
||||
.destination = dep.transportation.destination.name,
|
||||
.platform = dep.location.properties.platform,
|
||||
.date = date,
|
||||
.on_time = on_time,
|
||||
.delayed = delayed,
|
||||
.cancelled = dep.isCancelled,
|
||||
.information = infos,
|
||||
};
|
||||
|
||||
dep_i += 1;
|
||||
}
|
||||
|
||||
std.mem.sort(
|
||||
template.Departure,
|
||||
departures,
|
||||
{},
|
||||
template.Departure.cmpByTimeUnix,
|
||||
);
|
||||
|
||||
const context = template.Context{
|
||||
.station = efa_dm_resp.locations[0].name,
|
||||
.time = try std.fmt.allocPrint(
|
||||
arena.allocator(),
|
||||
"{d}:{d:0>2}",
|
||||
.{ now_local.hour, now_local.minute },
|
||||
),
|
||||
.departures = departures[0..@min(departures.len, options.max_items)],
|
||||
.show_operator = options.show_operator,
|
||||
};
|
||||
|
||||
const escaped_context = try context.escape(arena.allocator());
|
||||
|
||||
var tmp_file = try temp.TempFile.create(arena.allocator(), .{
|
||||
.pattern = "departures-*.html",
|
||||
});
|
||||
defer tmp_file.deinit();
|
||||
const path = try tmp_file.parent_dir.realpathAlloc(arena.allocator(), tmp_file.basename);
|
||||
{
|
||||
const file = try tmp_file.open(.{ .mode = .write_only });
|
||||
defer file.close();
|
||||
const writer = file.writer();
|
||||
try template.render(&escaped_context, writer);
|
||||
}
|
||||
|
||||
return try renderer.render(self.allocator, path, self.dimensions);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue