Skip to content

Commit 085ec0b

Browse files
feat: add exercise iterator module
- add exercise iteration functionality to a seperate module
1 parent f0cdcbd commit 085ec0b

2 files changed

Lines changed: 111 additions & 0 deletions

File tree

src/cli.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const STD = @import("std");
22

33
const STYLES = @import("styles.zig");
4+
const EXERCISE_ITERATOR = @import("exercise_iterator.zig");
45

56
var stdin_buffer: [1024]u8 = undefined;
67
var stdin_reader = STD.fs.File.stdin().reader(&stdin_buffer);

src/exercise_iterator.zig

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
const STD = @import("std");
2+
3+
const UTIL = @import("util.zig");
4+
5+
pub const ExerciseIterator = struct {
6+
const Self = @This();
7+
8+
allocator: STD.mem.Allocator,
9+
exercises_dir_path: []const u8,
10+
all_exercises: STD.ArrayList([]const u8) = .empty,
11+
completed_exercises: STD.ArrayList([]const u8) = .empty,
12+
current_index: usize = 0,
13+
14+
pub fn init(allocator: STD.mem.Allocator, dir_path: []const u8) !*Self {
15+
const self = try allocator.create(Self);
16+
self.* = .{
17+
.allocator = allocator,
18+
.exercises_dir_path = dir_path,
19+
};
20+
21+
try self.populateExercises();
22+
23+
return self;
24+
}
25+
26+
pub fn deinit(self: *Self) void {
27+
for (self.all_exercises.items) |path| {
28+
self.allocator.free(path);
29+
}
30+
self.all_exercises.deinit(self.allocator);
31+
32+
for (self.completed_exercises.items) |path| {
33+
self.allocator.free(path);
34+
}
35+
self.completed_exercises.deinit(self.allocator);
36+
37+
self.allocator.destroy(self);
38+
}
39+
40+
fn populateExercises(self: *Self) !void {
41+
const dir_tree: *UTIL.DIR_TREE = try UTIL.DIR_TREE.init(
42+
self.allocator,
43+
self.exercises_dir_path,
44+
);
45+
defer dir_tree.deinit(self.allocator);
46+
47+
var temp_list: STD.ArrayList([]const u8) = .empty;
48+
defer temp_list.deinit(self.allocator);
49+
50+
try dir_tree.iterateAndFilterTree(self.allocator, .{
51+
.include_filter = ".cpp",
52+
.is_move_semantics_enabled = true,
53+
.external_list = &temp_list,
54+
});
55+
56+
for (temp_list.items) |path| {
57+
const duplicated_path = try self.allocator.dupe(u8, path);
58+
try self.all_exercises.append(self.allocator, duplicated_path);
59+
}
60+
61+
STD.sort.insertion(
62+
[]const u8,
63+
self.all_exercises.items,
64+
{},
65+
struct {
66+
fn lessThan(_: void, a: []const u8, b: []const u8) bool {
67+
return STD.mem.lessThan(u8, a, b);
68+
}
69+
}.lessThan,
70+
);
71+
}
72+
73+
pub fn current(self: *Self) ?[]const u8 {
74+
if (self.current_index >= self.all_exercises.items.len) {
75+
return null;
76+
}
77+
return self.all_exercises.items[self.current_index];
78+
}
79+
80+
pub fn next(self: *Self) !void {
81+
const current_exercise = self.current() orelse return;
82+
try self.completed_exercises.append(self.allocator, current_exercise);
83+
self.current_index += 1;
84+
}
85+
86+
pub fn prev(self: *Self) void {
87+
if (self.current_index == 0) {
88+
return;
89+
}
90+
_ = self.completed_exercises.pop();
91+
self.current_index -= 1;
92+
}
93+
94+
pub fn reset(self: *Self) void {
95+
self.current_index = 0;
96+
self.completed_exercises.clearAndFree(self.allocator);
97+
}
98+
99+
pub fn total(self: Self) usize {
100+
return self.all_exercises.items.len;
101+
}
102+
103+
pub fn progress(self: Self) usize {
104+
return self.current_index;
105+
}
106+
107+
pub fn isCompleted(self: Self) bool {
108+
return self.current_index >= self.all_exercises.items.len;
109+
}
110+
};

0 commit comments

Comments
 (0)