rubyzip 0.5.12 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubyzip might be problematic. Click here for more details.
- data/ChangeLog +151 -17
- data/NEWS +13 -0
- data/README +2 -0
- data/Rakefile +2 -3
- data/TODO +2 -3
- data/lib/download_quizzes.rb +119 -0
- data/lib/quiz1/t/solutions/Bill Guindon/solitaire.rb +205 -0
- data/lib/quiz1/t/solutions/Carlos/solitaire.rb +111 -0
- data/lib/quiz1/t/solutions/Dennis Ranke/solitaire.rb +111 -0
- data/lib/quiz1/t/solutions/Florian Gross/solitaire.rb +301 -0
- data/lib/quiz1/t/solutions/Glen M. Lewis/solitaire.rb +268 -0
- data/lib/quiz1/t/solutions/James Edward Gray II/solitaire.rb +132 -0
- data/lib/quiz1/t/solutions/Jamis Buck/bin/main.rb +13 -0
- data/lib/quiz1/t/solutions/Jamis Buck/lib/cipher.rb +230 -0
- data/lib/quiz1/t/solutions/Jamis Buck/lib/cli.rb +24 -0
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_deck.rb +30 -0
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_key-stream.rb +19 -0
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_keying-algorithms.rb +31 -0
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_solitaire-cipher.rb +66 -0
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_unkeyed-algorithm.rb +17 -0
- data/lib/quiz1/t/solutions/Jamis Buck/test/tests.rb +2 -0
- data/lib/quiz1/t/solutions/Jim Menard/solitaire_cypher.rb +204 -0
- data/lib/quiz1/t/solutions/Jim Menard/test.rb +47 -0
- data/lib/quiz1/t/solutions/Moses Hohman/cipher.rb +97 -0
- data/lib/quiz1/t/solutions/Moses Hohman/deck.rb +140 -0
- data/lib/quiz1/t/solutions/Moses Hohman/solitaire.rb +14 -0
- data/lib/quiz1/t/solutions/Moses Hohman/test_cipher.rb +68 -0
- data/lib/quiz1/t/solutions/Moses Hohman/test_deck.rb +146 -0
- data/lib/quiz1/t/solutions/Moses Hohman/test_util.rb +38 -0
- data/lib/quiz1/t/solutions/Moses Hohman/testsuite.rb +5 -0
- data/lib/quiz1/t/solutions/Moses Hohman/util.rb +27 -0
- data/lib/quiz1/t/solutions/Niklas Frykholm/solitaire.rb +151 -0
- data/lib/quiz1/t/solutions/Thomas Leitner/solitaire.rb +198 -0
- data/lib/zip/ioextras.rb +17 -15
- data/lib/zip/zip.rb +394 -112
- data/lib/zip/zipfilesystem.rb +2 -2
- data/test/gentestfiles.rb +3 -1
- data/test/zipfilesystemtest.rb +2 -2
- data/test/ziptest.rb +34 -29
- metadata +35 -12
- data/samples/zipdialogui.rb +0 -80
- data/test/data/file2.txt.other +0 -0
- data/test/zlibtest.rb +0 -26
data/ChangeLog
CHANGED
@@ -1,3 +1,101 @@
|
|
1
|
+
2006-07-01 10:04 thomas
|
2
|
+
|
3
|
+
* Rakefile: Don't autorequire zip/zip - autorequire is deprecated.
|
4
|
+
|
5
|
+
2006-06-30 09:28 thomas
|
6
|
+
|
7
|
+
* Rakefile: [no log message]
|
8
|
+
|
9
|
+
2006-06-30 09:25 thomas
|
10
|
+
|
11
|
+
* NEWS, lib/zip/zip.rb: Bumped version number and reformatted NEWS
|
12
|
+
a bit.
|
13
|
+
|
14
|
+
2006-06-29 22:49 technorama
|
15
|
+
|
16
|
+
* lib/zip/zip.rb, NEWS: documentation additions
|
17
|
+
|
18
|
+
2006-04-30 06:25 technorama
|
19
|
+
|
20
|
+
* TODO, lib/zip/zip.rb, test/ziptest.rb: add documentation and test
|
21
|
+
for new ZipFile::extract
|
22
|
+
|
23
|
+
2006-04-30 06:22 technorama
|
24
|
+
|
25
|
+
* lib/zip/zip.rb: add some of the API suggestions from sf.net
|
26
|
+
#1281314
|
27
|
+
|
28
|
+
2006-04-30 05:55 technorama
|
29
|
+
|
30
|
+
* lib/zip/zip.rb: apply patch for bug #1446926
|
31
|
+
|
32
|
+
2006-04-30 05:54 technorama
|
33
|
+
|
34
|
+
* lib/zip/zip.rb: apply patch for bug #1459902
|
35
|
+
|
36
|
+
2006-04-26 17:17 technorama
|
37
|
+
|
38
|
+
* lib/zip/zip.rb: add ZipFile @restore_*, documentation update
|
39
|
+
|
40
|
+
2006-04-07 21:13 technorama
|
41
|
+
|
42
|
+
* test/: gentestfiles.rb, zipfilesystemtest.rb, ziptest.rb:
|
43
|
+
additional tests
|
44
|
+
|
45
|
+
2006-03-28 04:11 technorama
|
46
|
+
|
47
|
+
* lib/zip/zip.rb: start of unix_uid, unix_gid, restore_* support
|
48
|
+
|
49
|
+
2006-03-28 03:49 technorama
|
50
|
+
|
51
|
+
* lib/zip/zip.rb: follow_symlinks is now optional
|
52
|
+
|
53
|
+
2006-03-28 03:32 technorama
|
54
|
+
|
55
|
+
* lib/zip/zip.rb: add eof? methods
|
56
|
+
|
57
|
+
2006-03-28 03:31 technorama
|
58
|
+
|
59
|
+
* test/ziptest.rb: eof? tests
|
60
|
+
|
61
|
+
2006-02-26 09:57 technorama
|
62
|
+
|
63
|
+
* README: add to authors
|
64
|
+
|
65
|
+
2006-02-26 09:56 technorama
|
66
|
+
|
67
|
+
* TODO: [no log message]
|
68
|
+
|
69
|
+
2006-02-25 12:04 thomas
|
70
|
+
|
71
|
+
* lib/zip/zip.rb, test/ziptest.rb: Did away with ZipStreamableFile.
|
72
|
+
|
73
|
+
2006-02-23 08:03 technorama
|
74
|
+
|
75
|
+
* lib/zip/zip.rb: unix file permissions. symlink support. rework
|
76
|
+
ZipEntry and delegate classes. reduce memory usage during
|
77
|
+
decompression.
|
78
|
+
|
79
|
+
2006-02-22 23:44 technorama
|
80
|
+
|
81
|
+
* lib/zip/zipfilesystem.rb: update permissionInt for mkdir
|
82
|
+
|
83
|
+
2006-02-04 10:42 thomas
|
84
|
+
|
85
|
+
* lib/zip/: ioextras.rb, zip.rb: Merged patch from oss-ruby.
|
86
|
+
|
87
|
+
2005-11-19 16:17 thomas
|
88
|
+
|
89
|
+
* lib/zip/zip.rb: [no log message]
|
90
|
+
|
91
|
+
2005-11-08 08:23 thomas
|
92
|
+
|
93
|
+
* lib/zip/ioextras.rb: Accepted patch from oss-ruby
|
94
|
+
|
95
|
+
2005-10-07 09:54 thomas
|
96
|
+
|
97
|
+
* TODO: [no log message]
|
98
|
+
|
1
99
|
2005-09-06 21:19 thomas
|
2
100
|
|
3
101
|
* lib/zip/zip.rb: [no log message]
|
@@ -204,7 +302,9 @@
|
|
204
302
|
test/data/file1.txt, test/data/file1.txt.deflatedData,
|
205
303
|
test/data/file2.txt, test/data/notzippedruby.rb,
|
206
304
|
test/data/rubycode.zip, test/data/rubycode2.zip,
|
207
|
-
test/data/testDirectory.bin, test/data/zipWithDirs.zip
|
305
|
+
test/data/testDirectory.bin, test/data/zipWithDirs.zip,
|
306
|
+
zip/ioextras.rb, zip/stdrubyext.rb, zip/tempfile_bugfixed.rb,
|
307
|
+
zip/zip.rb, zip/zipfilesystem.rb, zip/ziprequire.rb: Changed
|
208
308
|
directory structure
|
209
309
|
|
210
310
|
2005-02-13 22:44 thomas
|
@@ -222,8 +322,8 @@
|
|
222
322
|
|
223
323
|
2004-12-12 11:22 thomas
|
224
324
|
|
225
|
-
* NEWS, TODO, samples/write_simple.rb: Fixed 'version
|
226
|
-
extract'-field wrong in local headers
|
325
|
+
* NEWS, TODO, samples/write_simple.rb, zip/zip.rb: Fixed 'version
|
326
|
+
needed to extract'-field wrong in local headers
|
227
327
|
|
228
328
|
2004-05-02 15:17 thomas
|
229
329
|
|
@@ -231,7 +331,7 @@
|
|
231
331
|
|
232
332
|
2004-04-02 07:25 thomas
|
233
333
|
|
234
|
-
* NEWS: Fix for FreeBSD 4.9
|
334
|
+
* NEWS, zip/zip.rb: Fix for FreeBSD 4.9
|
235
335
|
|
236
336
|
2004-03-29 00:28 thomas
|
237
337
|
|
@@ -241,29 +341,51 @@
|
|
241
341
|
|
242
342
|
* NEWS: [no log message]
|
243
343
|
|
344
|
+
2004-03-28 15:23 thomas
|
345
|
+
|
346
|
+
* zip/zip.rb: Use RUBY_VERSION not VERSION constant
|
347
|
+
|
348
|
+
2004-03-28 14:51 thomas
|
349
|
+
|
350
|
+
* zip/zip.rb: Only use bugfixed Tempfile implementation if the ruby
|
351
|
+
version hasnt been fixed (contributed by Nobu Nakada)
|
352
|
+
|
353
|
+
2004-03-28 14:46 thomas
|
354
|
+
|
355
|
+
* zip/tempfile_bugfixed.rb: Compatibility with DelegateClass in
|
356
|
+
ruby version 1.8.1 and newer
|
357
|
+
|
244
358
|
2004-03-27 16:09 thomas
|
245
359
|
|
246
|
-
* test/stdrubyexttest.rb
|
360
|
+
* test/stdrubyexttest.rb, zip/stdrubyext.rb: Patch for
|
361
|
+
stdrubyext.rb from Nobu Nakada
|
362
|
+
|
363
|
+
2004-03-27 15:52 thomas
|
364
|
+
|
365
|
+
* zip/: ioextras.rb, zip.rb, zipfilesystem.rb, ziprequire.rb: [no
|
366
|
+
log message]
|
247
367
|
|
248
368
|
2004-03-27 15:30 thomas
|
249
369
|
|
250
|
-
* test
|
251
|
-
to unix line-endings
|
370
|
+
* test/ioextrastest.rb, test/stdrubyexttest.rb, zip/ioextras.rb:
|
371
|
+
converted some files to unix line-endings
|
252
372
|
|
253
373
|
2004-03-25 16:34 thomas
|
254
374
|
|
255
|
-
* NEWS, install.rb
|
256
|
-
modifying zip files
|
375
|
+
* NEWS, install.rb, zip/tempfile_bugfixed.rb, zip/zip.rb:
|
376
|
+
Significantly reduced memory footprint when modifying zip files
|
257
377
|
|
258
378
|
2004-03-16 18:20 thomas
|
259
379
|
|
260
380
|
* install.rb, test/alltests.rb, test/ioextrastest.rb,
|
261
|
-
test/stdrubyexttest.rb, test/ziptest.rb
|
262
|
-
|
381
|
+
test/stdrubyexttest.rb, test/ziptest.rb, zip/ioextras.rb,
|
382
|
+
zip/zip.rb: IO utility classes moved to new file ioextras.rb.
|
383
|
+
Tests moved to new file ioextrastest.rb
|
263
384
|
|
264
385
|
2004-02-27 13:21 thomas
|
265
386
|
|
266
|
-
* NEWS: Optimization to avoid decompression and
|
387
|
+
* NEWS, zip/zip.rb: Optimization to avoid decompression and
|
388
|
+
recompression
|
267
389
|
|
268
390
|
2004-01-30 16:17 thomas
|
269
391
|
|
@@ -271,21 +393,31 @@
|
|
271
393
|
|
272
394
|
2004-01-30 16:07 thomas
|
273
395
|
|
274
|
-
* README, test/zipfilesystemtest.rb, test/ziptest.rb
|
396
|
+
* README, test/zipfilesystemtest.rb, test/ziptest.rb,
|
397
|
+
zip/stdrubyext.rb, zip/zip.rb, zip/zipfilesystem.rb: Applied
|
275
398
|
extra-field patch
|
276
399
|
|
277
400
|
2003-12-13 16:57 thomas
|
278
401
|
|
279
402
|
* TODO: [no log message]
|
280
403
|
|
404
|
+
2003-12-13 16:53 thomas
|
405
|
+
|
406
|
+
* zip/zip.rb: [no log message]
|
407
|
+
|
281
408
|
2003-12-10 00:25 thomas
|
282
409
|
|
283
410
|
* test/ziptest.rb: (Temporary) fix to bug reported by Takashi Sano
|
284
411
|
|
412
|
+
2003-10-03 11:05 thomas
|
413
|
+
|
414
|
+
* zip/: stdrubyext.rb, zip.rb: Thanks to Clifford Heath for
|
415
|
+
noticing that Time.to_binary_dos_date and time were reversed
|
416
|
+
|
285
417
|
2003-08-23 09:42 thomas
|
286
418
|
|
287
|
-
* test/ziptest.rb, NEWS: Fixed ZipFile.get_ouput_stream
|
288
|
-
was never written to zip
|
419
|
+
* test/ziptest.rb, zip/zip.rb, NEWS: Fixed ZipFile.get_ouput_stream
|
420
|
+
bug - data was never written to zip
|
289
421
|
|
290
422
|
2003-08-21 16:05 thomas
|
291
423
|
|
@@ -305,8 +437,10 @@
|
|
305
437
|
zipfilesystem.rb, zipfilesystemtest.rb, ziprequire.rb,
|
306
438
|
ziprequiretest.rb, ziptest.rb, samples/example.rb,
|
307
439
|
samples/example_filesystem.rb, samples/gtkRubyzip.rb,
|
308
|
-
samples/zipfind.rb
|
309
|
-
|
440
|
+
samples/zipfind.rb, zip/stdrubyext.rb, zip/zip.rb,
|
441
|
+
zip/zipfilesystem.rb, zip/ziprequire.rb: Moved all production
|
442
|
+
source files to zip/ so they are in the same dir as when they are
|
443
|
+
installed
|
310
444
|
|
311
445
|
2003-08-21 15:31 thomas
|
312
446
|
|
data/NEWS
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
= Version 0.9.1
|
2
|
+
|
3
|
+
Added symlink support and support for unix file permissions. Reduced
|
4
|
+
memory usage during decompression.
|
5
|
+
|
6
|
+
New methods ZipFile::[follow_symlinks, restore_times, restore_permissions, restore_ownership].
|
7
|
+
New methods ZipEntry::unix_perms, ZipInputStream::eof?.
|
8
|
+
Added documentation and test for new ZipFile::extract.
|
9
|
+
Added some of the API suggestions from sf.net #1281314.
|
10
|
+
Applied patch for sf.net bug #1446926.
|
11
|
+
Applied patch for sf.net bug #1459902.
|
12
|
+
Rework ZipEntry and delegate classes.
|
13
|
+
|
1
14
|
= Version 0.5.12
|
2
15
|
|
3
16
|
Fixed problem with writing binary content to a ZipFile in MS Windows.
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -50,9 +50,8 @@ spec = Gem::Specification.new do |s|
|
|
50
50
|
s.homepage = "http://rubyzip.sourceforge.net/"
|
51
51
|
s.platform = Gem::Platform::RUBY
|
52
52
|
s.summary = "rubyzip is a ruby module for reading and writing zip files"
|
53
|
-
s.files = PKG_FILES.to_a
|
53
|
+
s.files = PKG_FILES.to_a
|
54
54
|
s.require_path = 'lib'
|
55
|
-
s.autorequire = 'zip/zip'
|
56
55
|
end
|
57
56
|
|
58
57
|
Rake::GemPackageTask.new(spec) do |pkg|
|
@@ -70,7 +69,7 @@ end
|
|
70
69
|
desc "Publish documentation"
|
71
70
|
task :pdoc => [:rdoc] do
|
72
71
|
Rake::SshFreshDirPublisher.
|
73
|
-
new("thomas@rubyzip.sourceforge.net", "rubyzip/htdocs", "html").upload
|
72
|
+
new("thomas@rubyzip.sourceforge.net", "/home/groups/r/ru/rubyzip/htdocs", "html").upload
|
74
73
|
end
|
75
74
|
|
76
75
|
desc "Publish package"
|
data/TODO
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
|
2
|
+
* ZipInputStream: Support zip-files with trailing data descriptors
|
2
3
|
* Adjust rdoc stylesheet to advertise inherited methods if possible
|
3
4
|
* Suggestion: Add ZipFile/ZipInputStream example that demonstrates extracting all entries.
|
4
5
|
* Suggestion: ZipFile#extract destination should default to "."
|
5
6
|
* Suggestion: ZipEntry should have extract(), get_input_stream() methods etc
|
6
|
-
*
|
7
|
-
* provide alias for write -> syswrite in ioextras.rb
|
7
|
+
* SUggestion: ZipInputStream/ZipOutputStream should accept an IO object in addition to a filename.
|
8
8
|
* (is buffering used anywhere with write?)
|
9
|
-
* produce_input should take an optional buffer parameter.
|
10
9
|
* Inflater.sysread should pass the buffer to produce_input.
|
11
10
|
* Implement ZipFsDir.glob
|
12
11
|
* ZipFile.checkIntegrity method
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
|
3
|
+
rubygems = false
|
4
|
+
begin
|
5
|
+
require 'rubygems'
|
6
|
+
rubygems = true
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'open-uri'
|
11
|
+
require 'fileutils'
|
12
|
+
|
13
|
+
rubyzip = false
|
14
|
+
begin
|
15
|
+
require 'zip/zipfilesystem'
|
16
|
+
rubyzip = true
|
17
|
+
rescue LoadError
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
@address = "www.rubyquiz.com"
|
22
|
+
first = last = nil
|
23
|
+
|
24
|
+
first = ARGV[0].to_i if ARGV.size > 1
|
25
|
+
last = ARGV[1].to_i if ARGV.size > 2
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
#
|
30
|
+
# Download a binary file from the rubyquiz url
|
31
|
+
#
|
32
|
+
def download(file, todir = '.')
|
33
|
+
begin
|
34
|
+
puts "Downloading file #{file} from #{@address}"
|
35
|
+
c = open("http://#{@address}/#{file}").read
|
36
|
+
Dir.mkdir(todir) if not File.directory?(todir)
|
37
|
+
f = open("#{todir}/#{file}", 'wb')
|
38
|
+
f.puts c
|
39
|
+
f.close
|
40
|
+
rescue => e
|
41
|
+
if not File.exists?(fullfile)
|
42
|
+
$stderr.puts "Could not download file #{file} form #{@address}."
|
43
|
+
$stderr.puts e.to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
#
|
50
|
+
# Unzip the file using GNU's stand-alone unzip utility.
|
51
|
+
#
|
52
|
+
def unzip_gnu(file)
|
53
|
+
puts `unzip -o #{file}`
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
#
|
58
|
+
# Unzip the file using rubyzip library.
|
59
|
+
#
|
60
|
+
def unzip(x)
|
61
|
+
outdir = x.sub(/.*\//, '')
|
62
|
+
outdir = '.' if outdir == ""
|
63
|
+
Zip::ZipFile::open(x) { |zf|
|
64
|
+
zf.each { |e|
|
65
|
+
fpath = File.join(outdir, e.name)
|
66
|
+
FileUtils.mkdir_p(File.dirname(fpath))
|
67
|
+
zf.extract(e, fpath)
|
68
|
+
}
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
def get_index
|
75
|
+
c = open("http://#{@address}/").read
|
76
|
+
quizzes = c.scan /quiz(\d+).html/
|
77
|
+
return [ quizzes[0][0], quizzes[-1][0] ]
|
78
|
+
end
|
79
|
+
|
80
|
+
if not first or not last
|
81
|
+
f, l = get_index()
|
82
|
+
last = l unless last
|
83
|
+
first = f unless first
|
84
|
+
end
|
85
|
+
|
86
|
+
first = first.to_i
|
87
|
+
last = last.to_i
|
88
|
+
|
89
|
+
|
90
|
+
puts "Downloading quizzess #{first} to #{last}"
|
91
|
+
quizzes = (first..last)
|
92
|
+
quizzes.each { |q|
|
93
|
+
dir = "quiz#{q}"
|
94
|
+
|
95
|
+
#### Download HTML description
|
96
|
+
file = "quiz#{q}.html"
|
97
|
+
fullfile = "#{dir}/#{file}"
|
98
|
+
if not File.exists?(fullfile)
|
99
|
+
download( file, dir )
|
100
|
+
end
|
101
|
+
|
102
|
+
#### Download zip file
|
103
|
+
file = "quiz#{q}_sols.zip"
|
104
|
+
fullfile = "#{dir}/#{file}"
|
105
|
+
|
106
|
+
if not File.exists?(fullfile)
|
107
|
+
download( file, dir )
|
108
|
+
end
|
109
|
+
|
110
|
+
# Unzip and remove .zip file
|
111
|
+
Dir.chdir dir
|
112
|
+
if rubyzip
|
113
|
+
unzip file
|
114
|
+
else
|
115
|
+
unzip_gnu file
|
116
|
+
end
|
117
|
+
FileUtils.rm file
|
118
|
+
Dir.chdir '..'
|
119
|
+
}
|
@@ -0,0 +1,205 @@
|
|
1
|
+
# bail if you have nothing to do.
|
2
|
+
unless ARGV[0]
|
3
|
+
print <<-STOP_PRINT
|
4
|
+
Encrypts/decrypts a string of text.
|
5
|
+
Usage: Give it some text!
|
6
|
+
STOP_PRINT
|
7
|
+
exit
|
8
|
+
end
|
9
|
+
|
10
|
+
# the obligatory deck of cards.
|
11
|
+
###############################################################################
|
12
|
+
class Deck
|
13
|
+
attr_reader :cards, :order
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@cards = []
|
17
|
+
@order = []
|
18
|
+
build_deck
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
return @cards.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_deck
|
26
|
+
[:Clubs, :Diamonds, :Hearts, :Spades].each do |suit|
|
27
|
+
rank = 0
|
28
|
+
'A23456789TJQK'.each_byte do |name|
|
29
|
+
# 'real' cards have a rank value
|
30
|
+
rank += 1
|
31
|
+
add_card(name.chr, suit, rank)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Jokers have no rank value
|
36
|
+
'AB'.each_byte {|name| add_card(name.chr, :Joker, 0)}
|
37
|
+
end
|
38
|
+
|
39
|
+
# build order while adding.
|
40
|
+
def add_card(name, suit, rank)
|
41
|
+
card = Card.new(name, suit, rank)
|
42
|
+
@cards << card
|
43
|
+
@order << card.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
# Uses order to hunt for cards (Joker searches).
|
47
|
+
def find_card(name, suit)
|
48
|
+
return @order.index(Card.to_s(name, suit))
|
49
|
+
end
|
50
|
+
|
51
|
+
# does as many cuts as you give it.
|
52
|
+
def cut_cards(cuts)
|
53
|
+
cards = []
|
54
|
+
loc = 0
|
55
|
+
[cuts].flatten.each_with_index do |cut, idx|
|
56
|
+
cards[idx] = @cards[loc...cut]
|
57
|
+
loc = cut
|
58
|
+
end
|
59
|
+
cards << @cards[loc...@cards.length]
|
60
|
+
end
|
61
|
+
|
62
|
+
def cards=(cards)
|
63
|
+
# flatten to handle cut results.
|
64
|
+
@cards = cards.flatten
|
65
|
+
# rebuild @order each time the deck changes.
|
66
|
+
update_order
|
67
|
+
end
|
68
|
+
|
69
|
+
# simple, but not very efficient.
|
70
|
+
def update_order
|
71
|
+
@order = @cards.collect {|card| card.to_s}
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# the above deck is made up of...
|
77
|
+
###############################################################################
|
78
|
+
class Card
|
79
|
+
@@SUITS = {
|
80
|
+
:Clubs => 0,
|
81
|
+
:Diamonds => 13,
|
82
|
+
:Hearts => 26,
|
83
|
+
:Spades => 39,
|
84
|
+
:Joker => 53
|
85
|
+
}
|
86
|
+
|
87
|
+
def self.to_s(name, suit)
|
88
|
+
return name + ' ' + suit.to_s + "\n"
|
89
|
+
end
|
90
|
+
|
91
|
+
attr_reader :name, :suit, :rank
|
92
|
+
|
93
|
+
def initialize(name, suit, rank)
|
94
|
+
@name = name
|
95
|
+
@suit = suit
|
96
|
+
@rank = rank + @@SUITS[suit]
|
97
|
+
end
|
98
|
+
|
99
|
+
def to_s
|
100
|
+
Card.to_s(@name, @suit)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
###############################################################################
|
105
|
+
class Solitaire
|
106
|
+
|
107
|
+
attr_reader :deck
|
108
|
+
|
109
|
+
def initialize(text)
|
110
|
+
@deck = Deck.new
|
111
|
+
@text = text.to_s
|
112
|
+
end
|
113
|
+
|
114
|
+
def process
|
115
|
+
# does it look encrypted? 5 letter blocks all uppercase?
|
116
|
+
looks_encrypted = @text.gsub(/[A-Z]{5}\s?/, '').empty?
|
117
|
+
results = ''
|
118
|
+
|
119
|
+
# prep the text for parsing.
|
120
|
+
if looks_encrypted
|
121
|
+
# strip off the blanks for consistency
|
122
|
+
text = @text.gsub(/\s/, '')
|
123
|
+
else
|
124
|
+
# Discard any non A to Z characters, and uppercase all remaining
|
125
|
+
text = @text.upcase.gsub!(/[^A-Z]/, '')
|
126
|
+
# Split the message into five character groups,
|
127
|
+
words, padding = word_count(text, 5)
|
128
|
+
# using Xs to pad the last group
|
129
|
+
text += padding
|
130
|
+
end
|
131
|
+
|
132
|
+
# parse it, and build up results.
|
133
|
+
text.each_byte do |char|
|
134
|
+
if looks_encrypted
|
135
|
+
char -= next_key
|
136
|
+
char += 26 if char < 65
|
137
|
+
else
|
138
|
+
char += next_key
|
139
|
+
char -= 26 if char > 90
|
140
|
+
end
|
141
|
+
results += char.chr
|
142
|
+
end
|
143
|
+
|
144
|
+
return space_text(results, 5)
|
145
|
+
end
|
146
|
+
|
147
|
+
# counts words as 5 char blocks
|
148
|
+
def word_count(text, len)
|
149
|
+
words, strays = text.length.divmod(len)
|
150
|
+
words += 1 if strays > 0
|
151
|
+
pad = "X" * (len - strays)
|
152
|
+
return [words, pad]
|
153
|
+
end
|
154
|
+
|
155
|
+
def space_text(text, len)
|
156
|
+
# adds a space every 5 letters.
|
157
|
+
# not sure how efficient this is.
|
158
|
+
return text.unpack(('A' + len.to_s) * word_count(text, len)[0]).join(' ')
|
159
|
+
end
|
160
|
+
|
161
|
+
def shift_card(name, suit, count)
|
162
|
+
# find the card
|
163
|
+
idx = @deck.find_card(name, suit)
|
164
|
+
# remove it from the deck.
|
165
|
+
card = @deck.cards.slice!(idx)
|
166
|
+
# calculate new placement.
|
167
|
+
idx += count
|
168
|
+
# the slice above makes length 'look' zero-based
|
169
|
+
idx -= @deck.cards.length if idx > @deck.cards.length
|
170
|
+
|
171
|
+
# glue the deck together as cards before, card, cards after.
|
172
|
+
@deck.cards = @deck.cards[0...idx] + [card] +
|
173
|
+
@deck.cards[idx...@deck.cards.length]
|
174
|
+
end
|
175
|
+
|
176
|
+
def next_key
|
177
|
+
shift_card('A', :Joker, 1)
|
178
|
+
shift_card('B', :Joker, 2)
|
179
|
+
|
180
|
+
# find the 2 jokers, and sort them for the cut.
|
181
|
+
jokers = [@deck.find_card('A', :Joker), @deck.find_card('B', :Joker)].sort
|
182
|
+
# increment the 2nd joker pos -- cut uses 'up to, but not including'
|
183
|
+
jokers[1] += 1
|
184
|
+
# reverse works nicely for the triple cut.
|
185
|
+
@deck.cards = @deck.cut_cards(jokers).reverse
|
186
|
+
|
187
|
+
# get the value from the last card, and cut up to it.
|
188
|
+
cuts = @deck.cut_cards([@deck.cards.last.rank, @deck.cards.length - 1])
|
189
|
+
@deck.cards = cuts[1] + cuts[0] + cuts[2]
|
190
|
+
|
191
|
+
# read top card value, count down that many cards + 1
|
192
|
+
key = @deck.cards[@deck.cards[0].rank].rank
|
193
|
+
# convert it to a letter, adjust if needed.
|
194
|
+
key -= 26 if key > 26
|
195
|
+
|
196
|
+
# if key is still > 26, then it's a joker!
|
197
|
+
return (key) unless key > 26
|
198
|
+
# try again if it's a joker!
|
199
|
+
next_key
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
test = Solitaire.new(ARGV[0])
|
204
|
+
puts test.process
|
205
|
+
puts test.deck
|