From e1adeb52fee236e81da03afa9fc7810b42376ba4 Mon Sep 17 00:00:00 2001 From: falsycat Date: Sun, 30 Mar 2025 02:19:52 +0900 Subject: [PATCH] creates new project --- .gitignore | 2 + build.zig | 62 ++++++++++ build.zig.zon | 19 ++++ src/hncore/.DS_Store | Bin 0 -> 6148 bytes src/hncore/Digraph.zig | 249 +++++++++++++++++++++++++++++++++++++++++ src/hncore/root.zig | 5 + src/hnet/App.zig | 47 ++++++++ src/hnet/main.zig | 48 ++++++++ 8 files changed, 432 insertions(+) create mode 100644 .gitignore create mode 100644 build.zig create mode 100644 build.zig.zon create mode 100644 src/hncore/.DS_Store create mode 100644 src/hncore/Digraph.zig create mode 100644 src/hncore/root.zig create mode 100644 src/hnet/App.zig create mode 100644 src/hnet/main.zig diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db3cb54 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.zig-cache/ +/zig-out/ diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..09916ba --- /dev/null +++ b/build.zig @@ -0,0 +1,62 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + // ---- deps + const dvui_dep = b.dependency("dvui", .{ + .target = target, + .optimize = optimize, + .backend = .sdl, + .sdl3 = true, + }); + + // ---- library + const lib_mod = b.createModule(.{ + .root_source_file = b.path("src/hncore/root.zig"), + .target = target, + .optimize = optimize, + }); + + const lib = b.addLibrary(.{ + .linkage = .static, + .name = "hncore", + .root_module = lib_mod, + }); + b.installArtifact(lib); + + + // ---- executable + const exe_mod = b.createModule(.{ + .root_source_file = b.path("src/hnet/main.zig"), + .target = target, + .optimize = optimize, + }); + exe_mod.addImport("hncore", lib_mod); + exe_mod.addImport("dvui", dvui_dep.module("dvui_sdl")); + + const exe = b.addExecutable(.{ + .name = "hnet", + .root_module = exe_mod, + }); + b.installArtifact(exe); + + // ---- running + const run_cmd = b.addRunArtifact(exe); + run_cmd.step.dependOn(b.getInstallStep()); + if (b.args) |args| { + run_cmd.addArgs(args); + } + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); + + // ---- testing + const lib_unit_tests = b.addTest(.{ + .root_module = lib_mod, + }); + const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests); + + const test_step = b.step("test", "Run unit tests"); + test_step.dependOn(&run_lib_unit_tests.step); +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..811bb1d --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,19 @@ +.{ + .name = .heavens_net, + .version = "0.0.1", + .fingerprint = 0x5cbe403baf740fcb, + .minimum_zig_version = "0.15.0-dev.149+2b57f6b71", + + .dependencies = .{ + .dvui = .{ + .url = "https://github.com/david-vanderson/dvui/archive/9f446c8600b3385418c8926481076c335261f222.zip", + .hash = "dvui-0.2.0-AQFJmesqywBKCM6r9orR324EGhZvGsjhJw0ZHWcvwzyh", + }, + }, + + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/src/hncore/.DS_Store b/src/hncore/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 from) { + end = base_idx; + while ((end > 0) and (self.map.items[end-1].from != from)) { end -= 1; } + + begin = end; + while ((begin > 0) and (self.map.items[begin-1].from == from)) { begin -= 1; } + + } else { + begin = base_idx; + while ((begin > 0) and (self.map.items[begin-1].from == from)) { begin -= 1; } + + end = base_idx; + while ((end < n) and (self.map.items[end].from == from)) { end += 1; } + } + return .{ begin, end, }; + } + fn binsearch(self: *const @This(), from: T) ?usize { + if (self.map.items.len == 0) { + return null; + } + + var left : usize = 0; + var right: usize = self.map.items.len; + + var idx: usize = undefined; + while (left < right) { + idx = (left + right) / 2; + + const target = self.map.items[idx].from; + if (target < from) { + left = idx + 1; + } else if (target > from) { + right = idx -| 1; + } else { + break; + } + } + return idx; + } + fn compare_conn(_: void, a: Conn, b: Conn) bool { + return a.from < b.from; + } + }; +} + +test "check if connected" { + const Sut = Digraph(u8); + + const map = [_]Sut.Conn { + .{ .from = 3, .to = 0, }, + .{ .from = 0, .to = 1, }, + .{ .from = 1, .to = 3, }, + }; + + var sut = try Sut.init(std.testing.allocator, map[0..]); + defer sut.deinit(); + + try std.testing.expect(sut.is_connected(0, 1)); + try std.testing.expect(!sut.is_connected(1, 0)); + + try std.testing.expect(sut.is_connected(1, 3)); + try std.testing.expect(!sut.is_connected(3, 1)); + + try std.testing.expect(sut.is_connected(3, 0)); + try std.testing.expect(!sut.is_connected(0, 3)); + + try std.testing.expect(!sut.is_connected(0, 2)); + try std.testing.expect(!sut.is_connected(2, 0)); + + try std.testing.expect(!sut.is_connected(1, 2)); + try std.testing.expect(!sut.is_connected(2, 1)); +} +test "make new connection" { + const Sut = Digraph(u8); + + var sut = try Sut.init(std.testing.allocator, &.{}); + defer sut.deinit(); + + try std.testing.expect(try sut.connect_if(2, 1)); + + try std.testing.expect(sut.is_connected(2, 1)); + try std.testing.expect(!sut.is_connected(1, 2)); + + try sut.connect(3, 1); + + try std.testing.expect(sut.is_connected(3, 1)); + try std.testing.expect(!sut.is_connected(1, 3)); +} +test "making an existing connection fails" { + const Sut = Digraph(u8); + + const map = [_]Sut.Conn { + .{ .from = 0, .to = 1, }, + }; + var sut = try Sut.init(std.testing.allocator, map[0..]); + defer sut.deinit(); + + try std.testing.expect(!try sut.connect_if(0, 1)); + try std.testing.expectError(Sut.Error.AlreadyConnected, sut.connect(0, 1)); +} +test "disconnect an existing connection" { + const Sut = Digraph(u8); + + const map = [_]Sut.Conn { + .{ .from = 0, .to = 1, }, + .{ .from = 2, .to = 3, }, + }; + var sut = try Sut.init(std.testing.allocator, map[0..]); + defer sut.deinit(); + + try std.testing.expect(sut.disconnect_if(0, 1)); + try std.testing.expect(!sut.is_connected(0, 1)); + + try sut.disconnect(2, 3); + try std.testing.expect(!sut.is_connected(2, 3)); +} +test "disconnecting a missing connection fails" { + const Sut = Digraph(u8); + + var sut = try Sut.init(std.testing.allocator, &.{}); + defer sut.deinit(); + + try std.testing.expect(!sut.disconnect_if(0, 1)); + try std.testing.expectError(Sut.Error.NotConnected, sut.disconnect(1, 0)); +} +test "chaotic operation" { + const Sut = Digraph(u16); + + var sut = try Sut.init(std.testing.allocator, &.{}); + defer sut.deinit(); + + const N = 100; + for (0..N) |v| { + const x: Sut.Node = @intCast(v); + try sut.connect(x*%7, x*%13); + } + for (N/2..N) |v| { + const x: Sut.Node = @intCast(v); + try sut.disconnect(x*%7, x*%13); + } + for (0..N/2) |v| { + const x: Sut.Node = @intCast(v); + try std.testing.expect(sut.is_connected(x*%7, x*%13)); + } + for (N/2..N) |v| { + const x: Sut.Node = @intCast(v); + try std.testing.expect(!sut.is_connected(x*%7, x*%13)); + } +} diff --git a/src/hncore/root.zig b/src/hncore/root.zig new file mode 100644 index 0000000..d9fa89a --- /dev/null +++ b/src/hncore/root.zig @@ -0,0 +1,5 @@ +pub const Digraph = @import("./Digraph.zig").Digraph; + +test { + @import("std").testing.refAllDecls(@This()); +} diff --git a/src/hnet/App.zig b/src/hnet/App.zig new file mode 100644 index 0000000..3b3c2d4 --- /dev/null +++ b/src/hnet/App.zig @@ -0,0 +1,47 @@ +const std = @import("std"); +const dvui = @import("dvui"); +const hncore = @import("hncore"); + +pub const App = struct { + pub fn init(alloc: std.mem.Allocator) !App { + _ = alloc; + return App { + }; + } + pub fn deinit(self: *App) void { + _ = self; + } + + pub fn gui(self: *App) !void { + _ = self; + + try gui_menu(); + try gui_main(); + } + fn gui_menu() !void { + var root = try dvui.menu(@src(), .horizontal, .{ .background = true, .expand = .horizontal }); + defer root.deinit(); + + if (try dvui.menuItemLabel(@src(), "File", .{ .submenu = true }, .{})) |r| { + var float = try dvui.floatingMenu( + @src(), .{.from = dvui.Rect.fromPoint(dvui.Point{ .x = r.x, .y = r.y + r.h })}, .{}); + defer float.deinit(); + + if (try dvui.menuItemLabel(@src(), "Open", .{}, .{})) |_| { + } + } + } + fn gui_main() !void { + var box = try dvui.scrollArea(@src(), .{}, .{ + .expand = .both, + .color_fill = .{ .name = .fill_window }, + .padding = dvui.Rect.all(8), + }); + defer box.deinit(); + + if (try dvui.button(@src(), "Zoom In", .{}, .{})) { + } + if (try dvui.button(@src(), "Zoom In", .{}, .{})) { + } + } +}; diff --git a/src/hnet/main.zig b/src/hnet/main.zig new file mode 100644 index 0000000..1fd6c5f --- /dev/null +++ b/src/hnet/main.zig @@ -0,0 +1,48 @@ +const std = @import("std"); +const dvui = @import("dvui"); +const hncore = @import("hncore"); + +const App = @import("./App.zig").App; + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer if (gpa.deinit() == .leak) { + @panic("memory leak detected"); + }; + + var backend = try dvui.backend.initWindow(.{ + .allocator = gpa.allocator(), + .size = .{ .w = 800, .h = 600, }, + .min_size = .{ .w = 250, .h = 350, }, + .vsync = true, + .title = "Heaven's Net", + }); + defer backend.deinit(); + + var win = try dvui.Window.init(@src(), gpa.allocator(), backend.backend(), .{}); + defer win.deinit(); + + var app = try App.init(gpa.allocator()); + while (true) { + try win.begin( + win.beginWait(backend.hasEvent()), + ); + + const quit = try backend.addAllEvents(&win); + if (quit) { + break; + } + + try app.gui(); + + const end_micros = try win.end(.{}); + + backend.setCursor(win.cursorRequested()); + backend.textInputRect(win.textInputRequested()); + backend.renderPresent(); + + backend.waitEventTimeout( + win.waitTime(end_micros, null), + ); + } +}