vete 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/vete.rb +46 -27
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31328c3602f1174d697b56c9d0b8049986b68151975ed05c2febe3bab04d0c00
|
4
|
+
data.tar.gz: e4d99dd8303a7bcc8d589f66bb6ad0a0e2b79bfb718c7f2856f2e3a7aa558e63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0df917b8b8bb7cc72e0903130543e4e700b4264e8119b9f65d5c038cfa2dfb3538804945df489fcc27fa781deb18c923a2c540087dbf95b60c50f8a1eca48890
|
7
|
+
data.tar.gz: d05bac44008d71d71738b234d0d2f750fdfdaa4c5d3de24263dd72e1888039165c5d902bdb01510712e0741750ae57dca16a679728c9cf5e97384227d1af80b2
|
data/lib/vete.rb
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
# Author: Steve Shreeve (steve.shreeve@gmail.com)
|
5
5
|
# Date: Mar 21, 2023
|
6
6
|
# ============================================================================
|
7
|
+
# TODO: 1) progress should update until all workers have *finished*
|
8
|
+
# ============================================================================
|
7
9
|
|
8
10
|
STDOUT.sync = true
|
9
11
|
|
@@ -13,16 +15,20 @@ require "fileutils"
|
|
13
15
|
require "optparse"
|
14
16
|
require "thread"
|
15
17
|
|
16
|
-
|
18
|
+
@pid = Process.pid
|
19
|
+
|
20
|
+
trap("INT" ) { print clear + go; abort "\n" }
|
21
|
+
trap("WINCH") { print clear or draw if @pid == Process.pid }
|
17
22
|
|
18
23
|
OptionParser.new.instance_eval do
|
19
|
-
@version = "0.
|
24
|
+
@version = "0.3.0"
|
20
25
|
@banner = "usage: #{program_name} [options]"
|
21
26
|
|
22
27
|
on "-b", "--bar <width>" , "Progress bar width, in characters", Integer
|
23
28
|
on "-c", "--char <character>" , "Character to use for progress bar", String
|
24
|
-
on "-
|
29
|
+
on "-d", "--delay <mode>" , "Delay mode (rand, task, numeric)"
|
25
30
|
on "-h", "--help" , "Show help and command usage" do Kernel.abort to_s; end
|
31
|
+
on "-r", "--reset" , "Remove directory used for job processing and quit"
|
26
32
|
on "-v", "--version" , "Show version number" do Kernel.abort "#{program_name} #{@version}"; end
|
27
33
|
on "-w", "--workers <count>" , "Set the number of workers (default is 1)", Integer
|
28
34
|
|
@@ -31,10 +37,21 @@ end.parse!(into: opts={}) rescue abort($!.message)
|
|
31
37
|
|
32
38
|
# populate CLI options
|
33
39
|
@char = opts[:char ] || "•"; @char = @char[0]
|
40
|
+
@wait = opts[:delay ]
|
34
41
|
@nuke = opts[:reset ]
|
35
42
|
@wide = opts[:bar ] || 20
|
36
43
|
@work = opts[:workers] || 1
|
37
44
|
|
45
|
+
# handle wait mode
|
46
|
+
case @wait
|
47
|
+
when "rand", "task", nil
|
48
|
+
when /\A(?:0|[1-9]\d*|(?:0?\.|[1-9]\d*\.)\d*)\z/
|
49
|
+
@wait = @wait.to_f
|
50
|
+
@wait > 0 or abort "invalid delay time (#{@wait.to_f} secs)"
|
51
|
+
else
|
52
|
+
abort "invalid delay mode '#{@wait}'"
|
53
|
+
end
|
54
|
+
|
38
55
|
# define job directories
|
39
56
|
@vete = File.expand_path(".vete")
|
40
57
|
@todo = File.join(@vete, "todo")
|
@@ -42,7 +59,6 @@ end.parse!(into: opts={}) rescue abort($!.message)
|
|
42
59
|
@done = File.join(@vete, "done")
|
43
60
|
@bomb = File.join(@vete, "bomb")
|
44
61
|
|
45
|
-
|
46
62
|
def move(path, dest)
|
47
63
|
dest = File.join(dest, File.basename(path))
|
48
64
|
FileUtils.mv(path, dest, force: true, secure: true)
|
@@ -76,10 +92,10 @@ end
|
|
76
92
|
|
77
93
|
# https://www.cse.psu.edu/~kxc104/class/cmpen472/16f/hw/hw8/vt100ansi.htm
|
78
94
|
|
79
|
-
def clear
|
80
|
-
def cursor(on)
|
81
|
-
def go(r=1,c=1); "\e[#{r};#{c}H" ; end
|
82
|
-
def go!(...)
|
95
|
+
def clear(line=nil); line ? "\e[K" : "\e[2J" ; end
|
96
|
+
def cursor(on) ; print on ? "\e[?25h": "\e[?25l"; end
|
97
|
+
def go(r=1,c=1) ; "\e[#{r};#{c}H" ; end
|
98
|
+
def go!(...) ; print go(...) ; end
|
83
99
|
|
84
100
|
def fg(rgb=nil); rgb ? "\e[38;2;#{hx(rgb)}m" : "\e[39m"; end
|
85
101
|
def bg(rgb=nil); rgb ? "\e[48;2;#{hx(rgb)}m" : "\e[49m"; end
|
@@ -88,22 +104,22 @@ def hx(str=nil); str =~ /\A#?(?:(\h\h)(\h\h)(\h\h)|(\h)(\h)(\h))\z/ or return
|
|
88
104
|
[r.hex, g.hex, b.hex] * ";"
|
89
105
|
end
|
90
106
|
|
91
|
-
def draw(
|
107
|
+
def draw(live=0, done=0, bomb=0, jobs=0, info=nil)
|
92
108
|
|
93
109
|
# outer box
|
94
110
|
unless info
|
95
111
|
print [
|
96
112
|
clear,
|
97
|
-
go(2 +
|
98
|
-
go(1
|
113
|
+
go(2 + @work, @len + 3) + "└" + "─" * (@wide + 2) + "┘\n",
|
114
|
+
go(1 , @len + 3) + "┌" + "─" * (@wide + 2) + "┐\n",
|
99
115
|
].join
|
100
|
-
|
116
|
+
@work.times {|i| print " %*d │ %*s │\n" % [@len, i + 1, @wide, ""] }
|
101
117
|
return
|
102
118
|
end
|
103
119
|
|
104
120
|
# worker bars
|
105
|
-
dpct = done.to_f / jobs
|
106
121
|
lpct = live.to_f / jobs
|
122
|
+
dpct = done.to_f / jobs
|
107
123
|
most = info.values.max
|
108
124
|
info.each do |slot, this|
|
109
125
|
tpct = this.to_f / most
|
@@ -115,12 +131,12 @@ def draw(rows, done=0, live=0, bomb=0, jobs=0, info=nil)
|
|
115
131
|
gcol = dpct * @wide
|
116
132
|
ycol = lpct * @wide
|
117
133
|
print [
|
118
|
-
go(
|
134
|
+
go(@work + 3, @len + 5),
|
119
135
|
fg("fff"),
|
120
136
|
bg("58a65c") + @char * ( gcol ) , # green (done)
|
121
|
-
bg("f1bf42") + @char * ( ycol) , # yellow (live)
|
137
|
+
bg("f1bf42") + @char * ( ycol) , # yellow (live)
|
122
138
|
bg("d85140") + " " * (@wide - gcol - ycol).ceil, # red (left)
|
123
|
-
go(
|
139
|
+
go(@work + 3, @len + 5 + @wide + 3) + " %.1f%% done " % [dpct * 100],
|
124
140
|
bomb == 0 ? nil : (bg + " " + bg("f1bf42") + " #{bomb} bombed "),
|
125
141
|
].join
|
126
142
|
|
@@ -136,7 +152,7 @@ FileUtils.mkdir_p @live
|
|
136
152
|
FileUtils.mkdir_p @done
|
137
153
|
FileUtils.mkdir_p @bomb
|
138
154
|
|
139
|
-
|
155
|
+
100.times {|i| FileUtils.touch(File.join(@todo, (i + 1).to_s)) }
|
140
156
|
|
141
157
|
# ==[ Configure workers ]=====================================================
|
142
158
|
|
@@ -149,43 +165,46 @@ begin
|
|
149
165
|
jobs = list.size
|
150
166
|
info = Hash.new(0)
|
151
167
|
|
152
|
-
setup
|
168
|
+
setup if defined?(setup)
|
153
169
|
|
154
170
|
cursor(false)
|
155
|
-
draw
|
156
|
-
|
157
|
-
time = Time.now
|
158
|
-
done = 0
|
171
|
+
draw
|
159
172
|
live = 0
|
173
|
+
done = 0
|
160
174
|
bomb = 0
|
175
|
+
time = Time.now
|
161
176
|
Thread.new do
|
162
|
-
list.
|
177
|
+
list.each_with_index do |path, task|
|
163
178
|
slot = @que.pop
|
164
179
|
@mtx.synchronize {
|
165
180
|
live += 1
|
166
181
|
}
|
167
182
|
show = "Working on task " + File.basename(path)
|
168
|
-
print go(slot + 1, @len + 5 + @wide + 3) + show
|
183
|
+
print go(slot + 1, @len + 5 + @wide + 3) + show + clear(true)
|
169
184
|
if chld = fork # parent
|
170
185
|
Thread.new do
|
171
186
|
okay = Process.waitpid2(chld)[1] == 0
|
172
187
|
move(path, okay ? @done : @bomb)
|
173
188
|
@que.push(slot)
|
174
189
|
@mtx.synchronize {
|
175
|
-
done += 1
|
176
190
|
live -= 1
|
191
|
+
done += 1
|
177
192
|
bomb += 1 unless okay
|
178
193
|
info[slot] += 1
|
179
194
|
}
|
180
195
|
end
|
181
|
-
draw(
|
196
|
+
draw(live, done, bomb, jobs, info.dup)
|
182
197
|
else
|
198
|
+
case @wait
|
199
|
+
when "rand" then sleep rand(@work)
|
200
|
+
when "task" then sleep task
|
201
|
+
when Numeric then sleep task * @wait
|
202
|
+
end if task < @work
|
183
203
|
perform(slot, path)
|
184
204
|
exit
|
185
205
|
end
|
186
206
|
end
|
187
207
|
end.join
|
188
|
-
draw(@work, done, live, bomb, jobs, info)
|
189
208
|
secs = Time.now.to_f - time.to_f
|
190
209
|
|
191
210
|
# summary
|