rubylabs 0.7.5 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/bitlab.rb CHANGED
@@ -10,19 +10,21 @@ module RubyLabs
10
10
 
11
11
  module BitLab
12
12
 
13
+ QueueView = Struct.new(:queue)
14
+
13
15
  =begin rdoc
14
16
  Make a unique binary code for each item in array +a+, returning a Hash that
15
17
  associates each item with its code.
16
18
  =end
17
19
 
18
- def make_codes(a)
19
- n = log2(a.length).ceil
20
- res = Hash.new
21
- a.each_with_index do |x,i|
22
- res[x] = i.code(n)
20
+ def make_codes(a)
21
+ n = log2(a.length).ceil
22
+ res = Hash.new
23
+ a.each_with_index do |x,i|
24
+ res[x] = i.code(n)
25
+ end
26
+ return res
23
27
  end
24
- return res
25
- end
26
28
 
27
29
  =begin rdoc
28
30
  Print the codes in +a+ (an associative array made by +make_codes+ or the
@@ -30,21 +32,21 @@ end
30
32
  output, either +:by_code+ or +:by_name+.
31
33
  =end
32
34
 
33
- def print_codes(a, mode = :by_code)
34
- if mode == :by_code
35
- a.sort { |x,y| x[1] <=> y[1] }.each do |sym, code|
36
- printf "%s %s\n", code, sym
37
- end
38
- elsif mode == :by_name
39
- width = a.keys.map{ |x| x.length }.max
40
- a.keys.sort.each do |x|
41
- printf "%-#{width}s %s\n", x, a[x]
35
+ def print_codes(a, mode = :by_code)
36
+ if mode == :by_code
37
+ a.sort { |x,y| x[1] <=> y[1] }.each do |sym, code|
38
+ printf "%s %s\n", code, sym
39
+ end
40
+ elsif mode == :by_name
41
+ width = a.keys.map{ |x| x.length }.max
42
+ a.keys.sort.each do |x|
43
+ printf "%-#{width}s %s\n", x, a[x]
44
+ end
45
+ else
46
+ raise "print_codes: mode must be :by_code or :by_name"
42
47
  end
43
- else
44
- raise "print_codes: mode must be :by_code or :by_name"
48
+ return true
45
49
  end
46
- return true
47
- end
48
50
 
49
51
  =begin rdoc
50
52
  Make a Message object for the characters in string s. The second
@@ -55,26 +57,26 @@ end
55
57
  documentation of +decode+).
56
58
  =end
57
59
 
58
- def encode(s, type, opt = nil)
59
- if (type.class == Hash || type.class == Node)
60
- code = (type.class == Node) ? assign_codes(type) : type
61
- msg = Message.new(:packed)
62
- s.each_byte do |ch|
63
- msg << code[ch.chr]
64
- printf("%s: %s\n", ch.chr, code[ch.chr]) if opt == :trace
65
- end
66
- else
67
- msg = Message.new(:unpacked)
68
- s.each_byte do |ch|
69
- code = ch.code(8)
70
- code.add_parity_bit if type == :parity
71
- msg << code
72
- printf("%s: %s\n", ch.chr, code) if opt == :trace
60
+ def encode(s, type, opt = nil)
61
+ if (type.class == Hash || type.class == Node)
62
+ code = (type.class == Node) ? assign_codes(type) : type
63
+ msg = Message.new(:packed)
64
+ s.each_byte do |ch|
65
+ msg << code[ch.chr]
66
+ printf("%s: %s\n", ch.chr, code[ch.chr]) if opt == :trace
67
+ end
68
+ else
69
+ msg = Message.new(:unpacked)
70
+ s.each_byte do |ch|
71
+ code = ch.code(8)
72
+ code.add_parity_bit if type == :parity
73
+ msg << code
74
+ printf("%s: %s\n", ch.chr, code) if opt == :trace
75
+ end
73
76
  end
77
+ msg.encoding = type
78
+ return msg
74
79
  end
75
- msg.encoding = type
76
- return msg
77
- end
78
80
 
79
81
  =begin rdoc
80
82
  Decode a message using the specified decoding scheme.
@@ -87,44 +89,46 @@ end
87
89
  encoding scheme.
88
90
  =end
89
91
 
90
- def decode(m, type)
91
- raise "not a message" unless m.class == Message
92
- res = ""
93
- if type.class == Node # weird -- it appears case labels can't be class names...
94
- res = huffman_decode(m, type)
95
- elsif type.class == Code
96
- raise "packed decode not implemented"
97
- elsif type == :ascii
98
- m.array.each do |x|
99
- res << x.value.chr
100
- end
101
- elsif type == :parity
102
- m.array.each do |x|
103
- if x.even_parity?
104
- res << (x.value >> 1).chr
105
- else
106
- res << "?"
92
+ def decode(m, type)
93
+ raise "not a message" unless m.class == Message
94
+ res = ""
95
+ if type.class == Node # weird -- it appears case labels can't be class names...
96
+ res = huffman_decode(m, type)
97
+ elsif type.class == Code
98
+ raise "packed decode not implemented"
99
+ elsif type == :ascii
100
+ m.array.each do |x|
101
+ res << x.value.chr
102
+ end
103
+ elsif type == :parity
104
+ m.array.each do |x|
105
+ if x.even_parity?
106
+ res << (x.value >> 1).chr
107
+ elsif $KCODE[0] == ?U
108
+ res << "\xe2\x80\xa2"
109
+ else
110
+ res << "?"
111
+ end
107
112
  end
113
+ else
114
+ raise "unknown option: #{type}"
108
115
  end
109
- else
110
- raise "unknown option: #{type}"
116
+ return res
111
117
  end
112
- return res
113
- end
114
118
 
115
119
  =begin rdoc
116
120
  Simulate transmission of message +m+, adding +n+ random errors. Returns a
117
121
  copy of the Message object after making +n+ calls to the +flip+ method.
118
122
  =end
119
123
 
120
- def garbled(m, n)
121
- res = m.copy
122
- n.times do
123
- c = res.array[ rand(res.array.length) ]
124
- c.flip( rand(c.length) )
124
+ def garbled(m, n)
125
+ res = m.copy
126
+ n.times do
127
+ c = res.array[ rand(res.array.length) ]
128
+ c.flip( rand(c.length) )
129
+ end
130
+ return res
125
131
  end
126
- return res
127
- end
128
132
 
129
133
 
130
134
  =begin rdoc
@@ -132,35 +136,38 @@ end
132
136
  by letter name
133
137
  =end
134
138
 
135
- def read_frequencies(fn)
136
- a = Hash.new
137
- File.open(fn).each do |line|
138
- line.chomp!
139
- next if line.length == 0
140
- next if line[0] == ?#
141
- x = line[/^./]
142
- f = line[/\d+\.\d+/].to_f
143
- a[x] = f
139
+ def read_frequencies(fn)
140
+ a = Hash.new
141
+ if fn.class == Symbol
142
+ fn = File.join(@@bitsDirectory, fn.to_s + ".txt")
143
+ end
144
+ File.open(fn).each do |line|
145
+ line.chomp!
146
+ next if line.length == 0
147
+ next if line[0] == ?#
148
+ x = line[/^./]
149
+ f = line[/\d+\.\d+/].to_f
150
+ a[x] = f
151
+ end
152
+ return a
144
153
  end
145
- return a
146
- end
147
154
 
148
155
  =begin rdoc
149
156
  Huffman tree interface: Build a tree using frequencies in Hash +f+.
150
157
  =end
151
158
 
152
159
  # :begin :build_tree
153
- def build_tree(f)
154
- pq = init_queue(f)
160
+ def build_tree(f)
161
+ pq = init_queue(f)
155
162
 
156
- while pq.length > 1
157
- n1 = pq.shift
158
- n2 = pq.shift
159
- pq << Node.combine( n1, n2)
160
- end
163
+ while pq.length > 1
164
+ n1 = pq.shift
165
+ n2 = pq.shift
166
+ pq << Node.combine( n1, n2)
167
+ end
161
168
 
162
- return pq[0]
163
- end
169
+ return pq[0]
170
+ end
164
171
  # :end :build_tree
165
172
 
166
173
  =begin rdoc
@@ -173,15 +180,15 @@ end
173
180
  =end
174
181
 
175
182
  # :begin :assign_codes
176
- def assign_codes(tree, code = {}, prefix = Code.new(0,0))
177
- if tree.char != nil
178
- code[tree.char] = prefix
179
- else
180
- assign_codes(tree.left, code, prefix + 0)
181
- assign_codes(tree.right, code, prefix + 1)
183
+ def assign_codes(tree, code = {}, prefix = Code.new(0,0))
184
+ if tree.char != nil
185
+ code[tree.char] = prefix
186
+ else
187
+ assign_codes(tree.left, code, prefix + 0)
188
+ assign_codes(tree.right, code, prefix + 1)
189
+ end
190
+ return code
182
191
  end
183
- return code
184
- end
185
192
  # :end :assign_codes
186
193
 
187
194
  =begin rdoc
@@ -190,13 +197,13 @@ end
190
197
  =end
191
198
 
192
199
  # :begin :init_queue
193
- def init_queue(a)
194
- q = PriorityQueue.new
195
- a.each do |x,f|
196
- q << Node.new(x,f)
200
+ def init_queue(a)
201
+ q = PriorityQueue.new
202
+ a.each do |x,f|
203
+ q << Node.new(x,f)
204
+ end
205
+ return q
197
206
  end
198
- return q
199
- end
200
207
  # :end :init_queue
201
208
 
202
209
  =begin rdoc
@@ -205,66 +212,72 @@ end
205
212
  or the +decode+ method defined in the Message class.
206
213
  =end
207
214
 
208
- def huffman_decode(m, tree)
209
- res = ""
210
- path = tree
211
- m.each do |bit|
212
- if path.leaf?
213
- res << path.char
214
- path = tree
215
+ def huffman_decode(m, tree)
216
+ res = ""
217
+ path = tree
218
+ m.each do |bit|
219
+ if path.leaf?
220
+ res << path.char
221
+ path = tree
222
+ end
223
+ path = (bit == 0) ? path.left : path.right
215
224
  end
216
- path = (bit == 0) ? path.left : path.right
225
+ res << path.char if path.leaf?
226
+ return res
217
227
  end
218
- res << path.char if path.leaf?
219
- return res
220
- end
221
228
 
222
229
  =begin rdoc
223
- Huffman tree utility: read strings of binary digits from a file. Each line has a binary
224
- sequence, a tab, and an English word. Return two arrays, one a list of Message objects built
225
- from the binary sequences and the other a parallel list of words. Since the input is sorted
226
- by code length (shortest codes first) returning them in order allows student to choose a
227
- word to decode based on length.
230
+ Return an array of binary codes (so students
231
+ can text decoding skills)
228
232
  =end
229
233
 
230
- def read_codes(fn)
231
- codes = Array.new
232
- words = Array.new
233
- File.open(fn).each do |line|
234
- line.chomp!
235
- next if line.length == 0
236
- next if line[0] == ?#
237
- code = Code.new(0,0)
238
- line[/[01]+/].each_byte do |byte|
239
- code << byte[0] # add least significant digit of ASCII "0" or "1"
240
- end
241
- msg = Message.new(:packed)
242
- msg << code
243
- codes << msg
244
- words << line[/[a-z]+/]
234
+ def read_codes
235
+ codes = Array.new
236
+ fn = File.join(@@bitsDirectory, "testcodes.txt")
237
+ File.open(fn).each do |line|
238
+ line.chomp!
239
+ code = Code.new(0,0)
240
+ line.each_byte do |byte|
241
+ code << byte[0] # add least significant digit of ASCII "0" or "1"
242
+ end
243
+ msg = Message.new(:packed)
244
+ msg << code
245
+ codes << msg
246
+ end
247
+ return codes
245
248
  end
246
- return codes, words
247
- end
249
+
250
+ =begin rdoc
251
+ Return an array of binary codes (so students
252
+ can text decoding skills)
253
+ =end
254
+
255
+ def read_words
256
+ fn = File.join(@@bitsDirectory, "testwords.txt")
257
+ words = File.open(fn).readlines
258
+ return words.map { |x| x.chomp }
259
+ end
260
+
248
261
 
249
262
  =begin rdoc
250
263
  Huffman tree utility: generate a random string of length +n+ using the letter frequencies +f+.
251
264
  =end
252
265
 
253
- def generate_string(n, f)
254
- s = ""
255
- n.times do
256
- r = rand
257
- sum = 0
258
- f.each do |ch,x|
259
- sum += x
260
- if r < sum
261
- s += ch
262
- break
266
+ def generate_string(n, f)
267
+ s = ""
268
+ n.times do
269
+ r = rand
270
+ sum = 0
271
+ f.each do |ch,x|
272
+ sum += x
273
+ if r < sum
274
+ s += ch
275
+ break
276
+ end
263
277
  end
264
278
  end
279
+ return s
265
280
  end
266
- return s
267
- end
268
281
 
269
282
  =begin rdoc
270
283
  Class for nodes of a Huffman tree. All nodes have a frequency (+freq+) used to
@@ -279,42 +292,42 @@ end
279
292
  queue.
280
293
  =end
281
294
 
282
- class Node
283
-
284
- attr_accessor :freq, :char, :left, :right
295
+ class Node
285
296
 
286
- def initialize(char,freq)
287
- @char = char
288
- @freq = freq
289
- @left = @right = nil
290
- end
297
+ attr_accessor :freq, :char, :left, :right
291
298
 
292
- def Node.combine(n1,n2)
293
- node = Node.new(nil, n1.freq + n2.freq)
294
- node.left = n1
295
- node.right = n2
296
- return node
297
- end
299
+ def initialize(char,freq)
300
+ @char = char
301
+ @freq = freq
302
+ @left = @right = nil
303
+ end
298
304
 
299
- def <(x)
300
- x.class == Node && @freq < x.freq
301
- end
305
+ def Node.combine(n1,n2)
306
+ node = Node.new(nil, n1.freq + n2.freq)
307
+ node.left = n1
308
+ node.right = n2
309
+ return node
310
+ end
311
+
312
+ def <(x)
313
+ x.class == Node && @freq < x.freq
314
+ end
302
315
 
303
- def leaf?
304
- return @char != nil
305
- end
316
+ def leaf?
317
+ return @char != nil
318
+ end
306
319
 
307
- def inspect
308
- if leaf?
309
- sprintf "( %s: %.3f )", @char, @freq
310
- else
311
- sprintf "( %.3f %s %s )", @freq, @left.to_s, @right.to_s
312
- end
313
- end
320
+ def inspect
321
+ if leaf?
322
+ sprintf "( %s: %.3f )", @char, @freq
323
+ else
324
+ sprintf "( %.3f %s %s )", @freq, @left.to_s, @right.to_s
325
+ end
326
+ end
314
327
 
315
- alias to_s inspect
328
+ alias to_s inspect
316
329
 
317
- end # Node
330
+ end # Node
318
331
 
319
332
  =begin rdoc
320
333
  Code objects are variable-length binary numbers representing individual letters or members
@@ -349,101 +362,101 @@ end # Node
349
362
  # >> c1.flip(0)
350
363
  # => 10000000000000000000000000000000000000000000000000000000000000000000000001101000
351
364
 
352
- class Code
353
- attr_accessor :value, :length, :base
365
+ class Code
366
+ attr_accessor :value, :length, :base
354
367
 
355
- def initialize(value, length = 0, base = :binary)
356
- raise "Code: unknown base: #{base}" unless [:binary, :hex].include?(base)
357
- @value = value
358
- @length = length
359
- @base = base
360
- @has_parity_bit = false
361
- end
368
+ def initialize(value, length = 0, base = :binary)
369
+ raise "Code: unknown base: #{base}" unless [:binary, :hex].include?(base)
370
+ @value = value
371
+ @length = length
372
+ @base = base
373
+ @has_parity_bit = false
374
+ end
362
375
 
363
- def +(bit)
364
- raise "operation not defined for hex codes" unless @base == :binary
365
- val = (@value << 1) | bit[0]
366
- return Code.new(val, @length+1)
367
- end
376
+ def +(bit)
377
+ raise "operation not defined for hex codes" unless @base == :binary
378
+ val = (@value << 1) | bit[0]
379
+ return Code.new(val, @length+1)
380
+ end
368
381
 
369
- def <<(x)
370
- raise "operation not defined for hex codes" unless @base == :binary
371
- if x.class == Code
372
- val = x.value # val known to fit in x.length bits
373
- n = x.length
374
- else
375
- val = x[0] # val is a single bit
376
- n = 1
382
+ def <<(x)
383
+ raise "operation not defined for hex codes" unless @base == :binary
384
+ if x.class == Code
385
+ val = x.value # val known to fit in x.length bits
386
+ n = x.length
387
+ else
388
+ val = x[0] # val is a single bit
389
+ n = 1
390
+ end
391
+ @value <<= n
392
+ @value |= val # val can't have any higher order bits set -- see above
393
+ @length += n
394
+ return self
377
395
  end
378
- @value <<= n
379
- @value |= val # val can't have any higher order bits set -- see above
380
- @length += n
381
- return self
382
- end
383
396
 
384
- def [](i)
385
- if i.class == Range
386
- res = 0
387
- n = 0
388
- i.each { |j| res <<= 1; res |= @value[@length-j-1]; n += 1 }
389
- return Code.new(res, n)
390
- else
391
- return @value[@length-i-1]
397
+ def [](i)
398
+ if i.class == Range
399
+ res = 0
400
+ n = 0
401
+ i.each { |j| res <<= 1; res |= @value[@length-j-1]; n += 1 }
402
+ return Code.new(res, n)
403
+ else
404
+ return @value[@length-i-1]
405
+ end
392
406
  end
393
- end
394
407
 
395
- def parity_bit
396
- bit = 0
397
- for i in 0...@length
398
- bit ^= @value[i]
408
+ def parity_bit
409
+ bit = 0
410
+ for i in 0...@length
411
+ bit ^= @value[i]
412
+ end
413
+ return bit
399
414
  end
400
- return bit
401
- end
402
415
 
403
- def add_parity_bit
404
- @has_parity_bit = true
405
- return self << parity_bit
406
- end
416
+ def add_parity_bit
417
+ @has_parity_bit = true
418
+ return self << parity_bit
419
+ end
407
420
 
408
- def even_parity?
409
- return parity_bit() == 0
410
- end
421
+ def even_parity?
422
+ return parity_bit() == 0
423
+ end
411
424
 
412
- def flip(i)
413
- raise "bit index out of range" unless i < @length
414
- @value ^= (1 << (@length - i - 1))
415
- return self
416
- end
425
+ def flip(i)
426
+ raise "bit index out of range" unless i < @length
427
+ @value ^= (1 << (@length - i - 1))
428
+ return self
429
+ end
417
430
 
418
- def chr
419
- if @has_parity_bit
420
- if even_parity?
421
- return (@value >> 1).chr
422
- else
423
- return "?"
431
+ def chr
432
+ if @has_parity_bit
433
+ if even_parity?
434
+ return (@value >> 1).chr
435
+ else
436
+ return "?"
437
+ end
438
+ else
439
+ return @value.chr
424
440
  end
425
- else
426
- return @value.chr
427
441
  end
428
- end
429
442
 
430
- def <=>(x)
431
- return @value <=> x.value
432
- end
443
+ def <=>(x)
444
+ return @value <=> x.value
445
+ end
433
446
 
434
- def inspect
435
- return "" if @length == 0
436
- case @base
437
- when :binary
438
- return sprintf "%0#{@length}b", @value
439
- when :hex
440
- return sprintf "%0#{@length/4}X", @value
447
+ def inspect
448
+ return "" if @length == 0
449
+ case @base
450
+ when :binary
451
+ return sprintf "%0#{@length}b", @value
452
+ when :hex
453
+ return sprintf "%0#{@length/4}X", @value
454
+ end
441
455
  end
442
- end
443
456
 
444
- alias to_s inspect
457
+ alias to_s inspect
445
458
 
446
- end # Code
459
+ end # Code
447
460
 
448
461
  =begin rdoc
449
462
  Message objects are arrays of Codes. New codes are added by a call to <<.
@@ -458,98 +471,150 @@ end # Code
458
471
 
459
472
  # TODO: allow for the possibility that a code word being added to a packed code can be longer than 8 bits
460
473
 
461
- class Message
474
+ class Message
462
475
 
463
- attr_accessor :packed, :array, :encoding
476
+ attr_accessor :packed, :array, :encoding
464
477
 
465
- @@packsize = 8 # number of bits to pack into single code
478
+ @@packsize = 8 # number of bits to pack into single code
466
479
 
467
- def initialize(type)
468
- raise "Message: unknown type" unless [:packed, :unpacked].include? type
469
- if type == :packed
470
- @packed = true
471
- @array = [ Code.new(0,0) ]
472
- else
473
- @packed = false
474
- @array = [ ]
480
+ def initialize(type)
481
+ raise "Message: unknown type" unless [:packed, :unpacked].include? type
482
+ if type == :packed
483
+ @packed = true
484
+ @array = [ Code.new(0,0) ]
485
+ else
486
+ @packed = false
487
+ @array = [ ]
488
+ end
475
489
  end
476
- end
477
490
 
478
- def copy
479
- dup = self.clone # copies @packed, @encoding
480
- dup.array = Array.new
481
- @array.each { |x| dup.array << x.clone } # deep copy of @array
482
- return dup
483
- end
491
+ def copy
492
+ dup = self.clone # copies @packed, @encoding
493
+ dup.array = Array.new
494
+ @array.each { |x| dup.array << x.clone } # deep copy of @array
495
+ return dup
496
+ end
484
497
 
485
- def each
486
- @array.each do |byte|
487
- for i in 0...byte.length
488
- yield(byte[i])
498
+ def each
499
+ @array.each do |byte|
500
+ for i in 0...byte.length
501
+ yield(byte[i])
502
+ end
489
503
  end
504
+ return self
490
505
  end
491
- return self
492
- end
493
506
 
494
- def <<(x)
495
- raise "Message#<<: not a code" unless x.class == Code
496
- if @packed
497
- if @array[-1].length + x.length <= @@packsize
498
- @array[-1] << x
507
+ def <<(x)
508
+ raise "Message#<<: not a code" unless x.class == Code
509
+ if @packed
510
+ if @array[-1].length + x.length <= @@packsize
511
+ @array[-1] << x
512
+ else
513
+ n = @@packsize - @array[-1].length
514
+ m = x.length - n
515
+ @array[-1] << x[0...n]
516
+ @array << x[n...x.length]
517
+ end
499
518
  else
500
- n = @@packsize - @array[-1].length
501
- m = x.length - n
502
- @array[-1] << x[0...n]
503
- @array << x[n...x.length]
519
+ @array << x
504
520
  end
505
- else
506
- @array << x
521
+ return self
507
522
  end
508
- return self
509
- end
510
523
 
511
- def decode
512
- res = ""
513
- if @encoding.class == Symbol
514
- @array.each do |code|
515
- res << code.chr
524
+ def decode
525
+ res = ""
526
+ if @encoding.class == Symbol
527
+ @array.each do |code|
528
+ res << code.chr
529
+ end
530
+ elsif @encoding.class == Node
531
+ res = huffman_decode(self, @encoding)
532
+ else
533
+ res = unpack
516
534
  end
517
- elsif @encoding.class == Node
518
- res = huffman_decode(self, @encoding)
519
- else
520
- res = unpack
535
+ return res
521
536
  end
522
- return res
523
- end
524
537
 
525
- def unpack
526
- "unpack: not implemented"
527
- end
538
+ def unpack
539
+ "unpack: not implemented"
540
+ end
528
541
 
529
- def length
530
- @array.inject(0) { |sum, code| sum += code.length }
531
- end
542
+ def length
543
+ @array.inject(0) { |sum, code| sum += code.length }
544
+ end
532
545
 
533
- def print(option)
534
- "a message"
535
- end
546
+ def print(option)
547
+ "a message"
548
+ end
536
549
 
537
- def inspect
538
- if @packed
539
- return @array.join("")
540
- else
541
- return @array.join(" ")
542
- end
543
- end
550
+ def inspect
551
+ if @packed
552
+ return @array.join("")
553
+ else
554
+ return @array.join(" ")
555
+ end
556
+ end
557
+
558
+ alias to_s inspect
544
559
 
545
- alias to_s inspect
560
+ end # Message
546
561
 
547
- end # Message
562
+ =begin rdoc
563
+ Initialize the canvas with a drawing of a priority queue.
564
+ =end
565
+
566
+ =begin
567
+ TODO fill in this stub...
568
+ =end
569
+
570
+ def view_queue(pq, userOptions = {} )
571
+ options = @@queueOptions.merge(userOptions)
572
+ Canvas.init(300, 500, "BitLab")
573
+ @@drawing = QueueView.new(pq)
574
+ pq.on_canvas = true
575
+ Canvas.sync
576
+ return true
577
+ end
578
+
579
+ def redraw_queue(pq)
580
+ puts "redraw: #{pq.inspect}"
581
+ end
582
+
583
+ @@queueOptions = {
584
+ }
585
+
586
+ @@bitsDirectory = File.join(File.dirname(__FILE__), '..', 'data', 'huffman')
548
587
 
549
588
  end # BitLab
550
589
 
551
590
  end # RubyLabs
552
591
 
592
+ =begin rdoc
593
+ Add hooks to the PriorityQueue's shift and << methods so they check to see if the
594
+ queue is on the canvas, and if so, update the drawing when an item is removed or added.
595
+ =end
596
+
597
+ class PriorityQueue
598
+
599
+ attr_accessor :on_canvas
600
+
601
+ alias_method :pqappend, :<<
602
+
603
+ def <<(obj)
604
+ res = pqappend(obj)
605
+ redraw_queue(self) if on_canvas
606
+ return res
607
+ end
608
+
609
+ alias_method :pqshift, :shift
610
+
611
+ def shift
612
+ res = pqshift
613
+ redraw_queue(self) if on_canvas
614
+ return res
615
+ end
616
+
617
+ end
553
618
 
554
619
  class Fixnum
555
620