diff --git a/src/eink_feed_render/api/efa/models.zig b/src/eink_feed_render/api/efa/models.zig new file mode 100644 index 0000000..37c51e0 --- /dev/null +++ b/src/eink_feed_render/api/efa/models.zig @@ -0,0 +1,90 @@ +pub const TransportationProductClass = enum(u32) { + zug = 0, + s_bahn = 1, + u_bahn = 2, + stadtbahn = 3, + strassen_trambahn = 4, + stadtbus = 5, + regionalbus = 6, + schnellbus = 7, + seil_zahnradbahn = 8, + schiff = 9, + anruf_sammel_taxi = 10, + sonstige = 11, + flugzeug = 12, + zug_nv = 13, + zug_fv = 14, + zug_fv_m_zuschlag = 15, + zug_fv_m_spez_fpr = 16, + sev = 17, + zug_shuttle = 18, + buergerbus = 19, + rufbus_liniengebunden = 20, + rufbus = 21, + _, + + pub fn toString(self: TransportationProductClass) ?[]const u8 { + return switch (self) { + .zug => "Zug", + .s_bahn => "S-Bahn", + .u_bahn => "U-Bahn", + .stadtbahn => "Stadtbahn", + .strassen_trambahn => "Straßen-/Trambahn", + .stadtbus => "Stadtbus", + .regionalbus => "Regionalbus", + .schnellbus => "Schnellbus", + .seil_zahnradbahn => "Seil-/Zahnradbahn", + .schiff => "Schiff", + .anruf_sammel_taxi => "Anruf-Sammel-Taxi", + .sonstige => "Sonstige", + .flugzeug => "Flugzeug", + .zug_nv => "Zug (Nahverkehr)", + .zug_fv => "Zug (Fernverkehr)", + .zug_fv_m_zuschlag => "Zug (Fernverkehr) mit Zuschlag", + .zug_fv_m_spez_fpr => "Zug (Fernverkehr) mit spezifischer Fpr", + .sev => "SEV Schnienenersatzverkehr", + .zug_shuttle => "Zug Shuttle", + .buergerbus => "Bürgerbus", + .rufbus_liniengebunden => "Rufbus (liniengebunden)", + .rufbus => "Rufbus", + _ => null, + }; + } +}; + +pub const Location = struct { + id: []const u8, + name: []const u8, + properties: struct { + platform: ?[]const u8 = null, + }, +}; + +pub const StopEvent = struct { + location: Location, + departureTimePlanned: []const u8, + departureTimeBaseTimetable: []const u8, + departureTimeEstimated: ?[]const u8 = null, + transportation: struct { + name: []const u8, + product: struct { + class: TransportationProductClass, + }, + operator: ?struct { + name: []const u8, + } = null, + destination: struct { + name: []const u8, + }, + }, + hints: ?[]const struct { + content: []const u8, + type: []const u8, + } = null, + isCancelled: bool = false, +}; + +pub const DmResponse = struct { + locations: []const Location, + stopEvents: []const StopEvent, +}; diff --git a/src/eink_feed_render/apps/Departures/efa.zig b/src/eink_feed_render/api/efa/root.zig similarity index 61% rename from src/eink_feed_render/apps/Departures/efa.zig rename to src/eink_feed_render/api/efa/root.zig index b184d70..0d02df0 100644 --- a/src/eink_feed_render/apps/Departures/efa.zig +++ b/src/eink_feed_render/api/efa/root.zig @@ -2,99 +2,10 @@ const std = @import("std"); const escaper = @import("../../escaper.zig"); +pub const models = @import("models.zig"); + const log = std.log.scoped(.efa); -pub const ApiTransportationProductClass = enum(u32) { - zug = 0, - s_bahn = 1, - u_bahn = 2, - stadtbahn = 3, - strassen_trambahn = 4, - stadtbus = 5, - regionalbus = 6, - schnellbus = 7, - seil_zahnradbahn = 8, - schiff = 9, - anruf_sammel_taxi = 10, - sonstige = 11, - flugzeug = 12, - zug_nv = 13, - zug_fv = 14, - zug_fv_m_zuschlag = 15, - zug_fv_m_spez_fpr = 16, - sev = 17, - zug_shuttle = 18, - buergerbus = 19, - rufbus_liniengebunden = 20, - rufbus = 21, - _, - - pub fn toString(self: ApiTransportationProductClass) ?[]const u8 { - return switch (self) { - .zug => "Zug", - .s_bahn => "S-Bahn", - .u_bahn => "U-Bahn", - .stadtbahn => "Stadtbahn", - .strassen_trambahn => "Straßen-/Trambahn", - .stadtbus => "Stadtbus", - .regionalbus => "Regionalbus", - .schnellbus => "Schnellbus", - .seil_zahnradbahn => "Seil-/Zahnradbahn", - .schiff => "Schiff", - .anruf_sammel_taxi => "Anruf-Sammel-Taxi", - .sonstige => "Sonstige", - .flugzeug => "Flugzeug", - .zug_nv => "Zug (Nahverkehr)", - .zug_fv => "Zug (Fernverkehr)", - .zug_fv_m_zuschlag => "Zug (Fernverkehr) mit Zuschlag", - .zug_fv_m_spez_fpr => "Zug (Fernverkehr) mit spezifischer Fpr", - .sev => "SEV Schnienenersatzverkehr", - .zug_shuttle => "Zug Shuttle", - .buergerbus => "Bürgerbus", - .rufbus_liniengebunden => "Rufbus (liniengebunden)", - .rufbus => "Rufbus", - _ => null, - }; - } -}; - -pub const ApiLocation = struct { - id: []const u8, - name: []const u8, - properties: struct { - platform: ?[]const u8 = null, - }, -}; - -pub const ApiStopEvent = struct { - location: ApiLocation, - departureTimePlanned: []const u8, - departureTimeBaseTimetable: []const u8, - departureTimeEstimated: ?[]const u8 = null, - transportation: struct { - name: []const u8, - product: struct { - class: ApiTransportationProductClass, - }, - operator: ?struct { - name: []const u8, - } = null, - destination: struct { - name: []const u8, - }, - }, - hints: ?[]const struct { - content: []const u8, - type: []const u8, - } = null, - isCancelled: bool = false, -}; - -pub const DmResponse = struct { - locations: []const ApiLocation, - stopEvents: []const ApiStopEvent, -}; - pub const Client = struct { pub const Error = error{ InvalidResponse, @@ -170,7 +81,7 @@ pub const Client = struct { try std.io.getStdOut().writeAll(body); } - pub fn getDepartures(self: *const Self, stop_id: []const u8) !std.json.Parsed(DmResponse) { + pub fn getDepartures(self: *const Self, stop_id: []const u8) !std.json.Parsed(models.DmResponse) { const escaped_stop_id = try escaper.escapeUriComponent(self.allocator, stop_id); defer if (escaped_stop_id) |s| self.allocator.free(s); const url_stop_id = escaped_stop_id orelse stop_id; @@ -204,7 +115,7 @@ pub const Client = struct { defer self.allocator.free(body); const response = try std.json.parseFromSlice( - DmResponse, + models.DmResponse, self.allocator, body, .{ .allocate = .alloc_always, .ignore_unknown_fields = true }, diff --git a/src/eink_feed_render/api/root.zig b/src/eink_feed_render/api/root.zig new file mode 100644 index 0000000..8d90898 --- /dev/null +++ b/src/eink_feed_render/api/root.zig @@ -0,0 +1 @@ +pub const efa = @import("efa/root.zig"); diff --git a/src/eink_feed_render/apps/Departures/root.zig b/src/eink_feed_render/apps/Departures/root.zig index bb6f620..460cacc 100644 --- a/src/eink_feed_render/apps/Departures/root.zig +++ b/src/eink_feed_render/apps/Departures/root.zig @@ -5,7 +5,7 @@ const zdt = @import("zdt"); const Dimensions = @import("../../Dimensions.zig"); const renderer = @import("../../renderer.zig"); -pub const efa = @import("efa.zig"); +pub const api = @import("../../api/root.zig"); const template = @import("template/root.zig"); @@ -28,7 +28,7 @@ pub const RenderOptions = struct { show_operator: bool, }; -pub fn render(self: *const Self, efa_dm_resp: *const efa.DmResponse, options: RenderOptions) ![]const u8 { +pub fn render(self: *const Self, efa_dm_resp: *const api.efa.models.DmResponse, options: RenderOptions) ![]const u8 { const now_local = try options.now.tzConvert(.{ .tz = options.tz }); var arena = std.heap.ArenaAllocator.init(self.allocator); diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/boat.png b/src/eink_feed_render/apps/Departures/template/icons/img/boat.png deleted file mode 100644 index f49f410..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/boat.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/bus.png b/src/eink_feed_render/apps/Departures/template/icons/img/bus.png deleted file mode 100644 index 5598cff..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/bus.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/flight.png b/src/eink_feed_render/apps/Departures/template/icons/img/flight.png deleted file mode 100644 index f6416af..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/flight.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/gondola.png b/src/eink_feed_render/apps/Departures/template/icons/img/gondola.png deleted file mode 100644 index ead5e99..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/gondola.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/no_transfer.png b/src/eink_feed_render/apps/Departures/template/icons/img/no_transfer.png deleted file mode 100644 index ee12871..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/no_transfer.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/shuttle.png b/src/eink_feed_render/apps/Departures/template/icons/img/shuttle.png deleted file mode 100644 index bc9b2e9..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/shuttle.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/subway.png b/src/eink_feed_render/apps/Departures/template/icons/img/subway.png deleted file mode 100644 index ad532af..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/subway.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/train.png b/src/eink_feed_render/apps/Departures/template/icons/img/train.png deleted file mode 100644 index d482e8d..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/train.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/img/tram.png b/src/eink_feed_render/apps/Departures/template/icons/img/tram.png deleted file mode 100644 index 718586e..0000000 Binary files a/src/eink_feed_render/apps/Departures/template/icons/img/tram.png and /dev/null differ diff --git a/src/eink_feed_render/apps/Departures/template/icons/root.zig b/src/eink_feed_render/apps/Departures/template/icons/root.zig index bfd53c1..e4e554a 100644 --- a/src/eink_feed_render/apps/Departures/template/icons/root.zig +++ b/src/eink_feed_render/apps/Departures/template/icons/root.zig @@ -1,8 +1,31 @@ const std = @import("std"); -const efa = @import("../../efa.zig"); +const api = @import("../../../../api/root.zig"); +const embed = @import("../../../../embed.zig"); -pub fn iconFromTransportationProductClass(class: efa.ApiTransportationProductClass) ?[]const u8 { +pub const data = embed.embedBase64Files( + (struct { + fn inner(comptime path: []const u8) []const u8 { + return @embedFile(path); + } + }).inner, + "image/svg+xml", + "svg", + "svg", + &.{ + "train", + "subway", + "tram", + "bus", + "shuttle", + "gondola", + "flight", + "boat", + "no_transfer", + }, +){}; + +pub fn iconFromTransportationProductClass(class: api.efa.models.TransportationProductClass) ?embed.EncodedFile { return switch (class) { .zug, .s_bahn, @@ -11,11 +34,11 @@ pub fn iconFromTransportationProductClass(class: efa.ApiTransportationProductCla .zug_fv_m_zuschlag, .zug_fv_m_spez_fpr, .zug_shuttle, - => train, + => data.train, - .u_bahn => subway, + .u_bahn => data.subway, - .stadtbahn, .strassen_trambahn => tram, + .stadtbahn, .strassen_trambahn => data.tram, .stadtbus, .regionalbus, @@ -24,40 +47,18 @@ pub fn iconFromTransportationProductClass(class: efa.ApiTransportationProductCla .rufbus_liniengebunden, .rufbus, .anruf_sammel_taxi, - => bus, + => data.bus, - .seil_zahnradbahn => gondola, + .seil_zahnradbahn => data.gondola, - .schiff => boat, + .schiff => data.boat, .sonstige => null, - .flugzeug => flight, + .flugzeug => data.flight, - .sev => no_transfer, + .sev => data.no_transfer, _ => null, }; } - -fn encodePng(comptime path: []const u8) []const u8 { - const raw = @embedFile(path); - const len = std.base64.standard.Encoder.calcSize(raw.len); - var buf: [len]u8 = undefined; - { - @setEvalBranchQuota(1_000_000); - _ = std.base64.standard.Encoder.encode(&buf, raw); - } - const final = buf; - return &final; -} - -pub const train = encodePng("img/train.png"); -pub const subway = encodePng("img/subway.png"); -pub const tram = encodePng("img/tram.png"); -pub const bus = encodePng("img/bus.png"); -pub const shuttle = encodePng("img/shuttle.png"); -pub const gondola = encodePng("img/gondola.png"); -pub const flight = encodePng("img/flight.png"); -pub const boat = encodePng("img/boat.png"); -pub const no_transfer = encodePng("img/no_transfer.png"); diff --git a/src/eink_feed_render/apps/Departures/template/root.zig b/src/eink_feed_render/apps/Departures/template/root.zig index 862dc59..382bcfb 100644 --- a/src/eink_feed_render/apps/Departures/template/root.zig +++ b/src/eink_feed_render/apps/Departures/template/root.zig @@ -1,7 +1,7 @@ const std = @import("std"); const escaper = @import("../../../escaper.zig"); -const efa = @import("../efa.zig"); +const api = @import("../../../api/root.zig"); const icons = @import("icons/root.zig"); @@ -9,7 +9,7 @@ pub const Departure = struct { time: []const u8, time_unix: i128, line: []const u8, - transportation_product_class: efa.ApiTransportationProductClass, + transportation_product_class: api.efa.models.TransportationProductClass, operator: ?[]const u8, destination: []const u8, platform: ?[]const u8, @@ -188,13 +188,16 @@ pub fn render(context: *const Context, writer: anytype) !void { ); } - if (icons.iconFromTransportationProductClass(departure.transportation_product_class)) |img| { + if (icons.iconFromTransportationProductClass(departure.transportation_product_class)) |file| { try writer.print( \\