rubyzip 0.9.1 → 0.9.4
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 +92 -450
- data/NEWS +18 -0
- data/README +1 -1
- data/Rakefile +14 -13
- data/install.rb +4 -3
- data/lib/zip/ioextras.rb +11 -1
- data/lib/zip/stdrubyext.rb +0 -0
- data/lib/zip/tempfile_bugfixed.rb +0 -0
- data/lib/zip/zip.rb +57 -24
- data/lib/zip/zipfilesystem.rb +1 -0
- data/lib/zip/ziprequire.rb +0 -0
- data/samples/example.rb +0 -0
- data/samples/example_filesystem.rb +0 -1
- data/samples/gtkRubyzip.rb +0 -0
- data/samples/qtzip.rb +0 -0
- data/samples/write_simple.rb +0 -0
- data/samples/zipfind.rb +0 -0
- data/test/alltests.rb +0 -0
- data/test/data/notzippedruby.rb +0 -0
- data/test/gentestfiles.rb +0 -0
- data/test/ioextrastest.rb +0 -0
- data/test/stdrubyexttest.rb +0 -0
- data/test/zipfilesystemtest.rb +14 -4
- data/test/ziprequiretest.rb +0 -0
- data/test/ziptest.rb +30 -9
- metadata +76 -88
- data/lib/download_quizzes.rb +0 -119
- data/lib/quiz1/t/solutions/Bill Guindon/solitaire.rb +0 -205
- data/lib/quiz1/t/solutions/Carlos/solitaire.rb +0 -111
- data/lib/quiz1/t/solutions/Dennis Ranke/solitaire.rb +0 -111
- data/lib/quiz1/t/solutions/Florian Gross/solitaire.rb +0 -301
- data/lib/quiz1/t/solutions/Glen M. Lewis/solitaire.rb +0 -268
- data/lib/quiz1/t/solutions/James Edward Gray II/solitaire.rb +0 -132
- data/lib/quiz1/t/solutions/Jamis Buck/bin/main.rb +0 -13
- data/lib/quiz1/t/solutions/Jamis Buck/lib/cipher.rb +0 -230
- data/lib/quiz1/t/solutions/Jamis Buck/lib/cli.rb +0 -24
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_deck.rb +0 -30
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_key-stream.rb +0 -19
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_keying-algorithms.rb +0 -31
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_solitaire-cipher.rb +0 -66
- data/lib/quiz1/t/solutions/Jamis Buck/test/tc_unkeyed-algorithm.rb +0 -17
- data/lib/quiz1/t/solutions/Jamis Buck/test/tests.rb +0 -2
- data/lib/quiz1/t/solutions/Jim Menard/solitaire_cypher.rb +0 -204
- data/lib/quiz1/t/solutions/Jim Menard/test.rb +0 -47
- data/lib/quiz1/t/solutions/Moses Hohman/cipher.rb +0 -97
- data/lib/quiz1/t/solutions/Moses Hohman/deck.rb +0 -140
- data/lib/quiz1/t/solutions/Moses Hohman/solitaire.rb +0 -14
- data/lib/quiz1/t/solutions/Moses Hohman/test_cipher.rb +0 -68
- data/lib/quiz1/t/solutions/Moses Hohman/test_deck.rb +0 -146
- data/lib/quiz1/t/solutions/Moses Hohman/test_util.rb +0 -38
- data/lib/quiz1/t/solutions/Moses Hohman/testsuite.rb +0 -5
- data/lib/quiz1/t/solutions/Moses Hohman/util.rb +0 -27
- data/lib/quiz1/t/solutions/Niklas Frykholm/solitaire.rb +0 -151
- data/lib/quiz1/t/solutions/Thomas Leitner/solitaire.rb +0 -198
data/test/ziprequiretest.rb
CHANGED
File without changes
|
data/test/ziptest.rb
CHANGED
@@ -5,6 +5,7 @@ $VERBOSE = true
|
|
5
5
|
$: << "../lib"
|
6
6
|
|
7
7
|
require 'test/unit'
|
8
|
+
require 'fileutils'
|
8
9
|
require 'zip/zip'
|
9
10
|
require 'gentestfiles'
|
10
11
|
|
@@ -631,6 +632,23 @@ class ZipOutputStreamTest < Test::Unit::TestCase
|
|
631
632
|
end
|
632
633
|
end
|
633
634
|
|
635
|
+
def test_put_next_entry
|
636
|
+
stored_text = "hello world in stored text"
|
637
|
+
entry_name = "file1"
|
638
|
+
comment = "my comment"
|
639
|
+
ZipOutputStream.open(TEST_ZIP.zip_name) do
|
640
|
+
|zos|
|
641
|
+
zos.put_next_entry(entry_name, comment, nil, ZipEntry::STORED)
|
642
|
+
zos << stored_text
|
643
|
+
end
|
644
|
+
|
645
|
+
assert(File.read(TEST_ZIP.zip_name).grep(stored_text))
|
646
|
+
ZipFile.open(TEST_ZIP.zip_name) do
|
647
|
+
|zf|
|
648
|
+
assert_equal(stored_text, zf.read(entry_name))
|
649
|
+
end
|
650
|
+
end
|
651
|
+
|
634
652
|
def assert_i_o_error_in_closed_stream
|
635
653
|
assert_raise(IOError) {
|
636
654
|
zos = ZipOutputStream.new("test_putOnClosedStream.zip")
|
@@ -1016,7 +1034,7 @@ module CommonZipFileFixture
|
|
1016
1034
|
|
1017
1035
|
def setup
|
1018
1036
|
File.delete(EMPTY_FILENAME) if File.exists?(EMPTY_FILENAME)
|
1019
|
-
|
1037
|
+
FileUtils.cp(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
|
1020
1038
|
end
|
1021
1039
|
end
|
1022
1040
|
|
@@ -1126,7 +1144,7 @@ class ZipFileTest < Test::Unit::TestCase
|
|
1126
1144
|
def test_remove
|
1127
1145
|
entryToRemove, *remainingEntries = TEST_ZIP.entry_names
|
1128
1146
|
|
1129
|
-
|
1147
|
+
FileUtils.cp(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
|
1130
1148
|
|
1131
1149
|
zf = ZipFile.new(TEST_ZIP.zip_name)
|
1132
1150
|
assert(zf.entries.map { |e| e.name }.include?(entryToRemove))
|
@@ -1141,24 +1159,27 @@ class ZipFileTest < Test::Unit::TestCase
|
|
1141
1159
|
zfRead.close
|
1142
1160
|
end
|
1143
1161
|
|
1144
|
-
|
1145
1162
|
def test_rename
|
1146
1163
|
entryToRename, *remainingEntries = TEST_ZIP.entry_names
|
1147
|
-
|
1164
|
+
|
1148
1165
|
zf = ZipFile.new(TEST_ZIP.zip_name)
|
1149
1166
|
assert(zf.entries.map { |e| e.name }.include?(entryToRename))
|
1150
|
-
|
1151
|
-
|
1167
|
+
|
1168
|
+
contents = zf.read(entryToRename)
|
1169
|
+
newName = "changed entry name"
|
1152
1170
|
assert(! zf.entries.map { |e| e.name }.include?(newName))
|
1153
1171
|
|
1154
1172
|
zf.rename(entryToRename, newName)
|
1155
1173
|
assert(zf.entries.map { |e| e.name }.include?(newName))
|
1156
1174
|
|
1175
|
+
assert_equal(contents, zf.read(newName))
|
1176
|
+
|
1157
1177
|
zf.close
|
1158
1178
|
|
1159
1179
|
zfRead = ZipFile.new(TEST_ZIP.zip_name)
|
1160
1180
|
assert(zfRead.entries.map { |e| e.name }.include?(newName))
|
1161
|
-
|
1181
|
+
assert_equal(contents, zf.read(newName))
|
1182
|
+
zfRead.close
|
1162
1183
|
end
|
1163
1184
|
|
1164
1185
|
def test_renameToExistingEntry
|
@@ -1271,12 +1292,12 @@ class ZipFileTest < Test::Unit::TestCase
|
|
1271
1292
|
# can delete the file you used to add the entry to the zip file
|
1272
1293
|
# with
|
1273
1294
|
def test_commitUseZipEntry
|
1274
|
-
|
1295
|
+
FileUtils.cp(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt")
|
1275
1296
|
zf = ZipFile.open(TEST_ZIP.zip_name)
|
1276
1297
|
zf.add("okToDelete.txt", "okToDelete.txt")
|
1277
1298
|
assert_contains(zf, "okToDelete.txt")
|
1278
1299
|
zf.commit
|
1279
|
-
File.
|
1300
|
+
File.rename("okToDelete.txt", "okToDeleteMoved.txt")
|
1280
1301
|
assert_contains(zf, "okToDelete.txt", "okToDeleteMoved.txt")
|
1281
1302
|
end
|
1282
1303
|
|
metadata
CHANGED
@@ -1,97 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.6
|
3
|
-
specification_version: 1
|
4
2
|
name: rubyzip
|
5
3
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.9.
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
- lib
|
11
|
-
email: thomas(at)sondergaard.cc
|
12
|
-
homepage: http://rubyzip.sourceforge.net/
|
13
|
-
rubyforge_project:
|
14
|
-
description:
|
4
|
+
version: 0.9.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas Sondergaard
|
15
8
|
autorequire:
|
16
|
-
default_executable:
|
17
9
|
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-01 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: thomas(at)sondergaard.cc
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- NEWS
|
27
|
+
- TODO
|
28
|
+
- ChangeLog
|
29
|
+
- install.rb
|
30
|
+
- Rakefile
|
31
|
+
- samples/example.rb
|
32
|
+
- samples/gtkRubyzip.rb
|
33
|
+
- samples/write_simple.rb
|
34
|
+
- samples/zipfind.rb
|
35
|
+
- samples/example_filesystem.rb
|
36
|
+
- samples/qtzip.rb
|
37
|
+
- test/stdrubyexttest.rb
|
38
|
+
- test/alltests.rb
|
39
|
+
- test/ziptest.rb
|
40
|
+
- test/ioextrastest.rb
|
41
|
+
- test/ziprequiretest.rb
|
42
|
+
- test/zipfilesystemtest.rb
|
43
|
+
- test/gentestfiles.rb
|
44
|
+
- test/data/rubycode2.zip
|
45
|
+
- test/data/file1.txt
|
46
|
+
- test/data/testDirectory.bin
|
47
|
+
- test/data/zipWithDirs.zip
|
48
|
+
- test/data/file2.txt
|
49
|
+
- test/data/file1.txt.deflatedData
|
50
|
+
- test/data/notzippedruby.rb
|
51
|
+
- test/data/rubycode.zip
|
52
|
+
- lib/zip/zipfilesystem.rb
|
53
|
+
- lib/zip/stdrubyext.rb
|
54
|
+
- lib/zip/tempfile_bugfixed.rb
|
55
|
+
- lib/zip/ioextras.rb
|
56
|
+
- lib/zip/zip.rb
|
57
|
+
- lib/zip/ziprequire.rb
|
18
58
|
has_rdoc: false
|
19
|
-
|
59
|
+
homepage: http://rubyzip.sourceforge.net/
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
20
66
|
requirements:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "0"
|
25
76
|
version:
|
26
|
-
platform: ruby
|
27
|
-
authors:
|
28
|
-
- Thomas Sondergaard
|
29
|
-
files:
|
30
|
-
- README
|
31
|
-
- NEWS
|
32
|
-
- TODO
|
33
|
-
- ChangeLog
|
34
|
-
- install.rb
|
35
|
-
- Rakefile
|
36
|
-
- samples/example.rb
|
37
|
-
- samples/example_filesystem.rb
|
38
|
-
- samples/gtkRubyzip.rb
|
39
|
-
- samples/qtzip.rb
|
40
|
-
- samples/write_simple.rb
|
41
|
-
- samples/zipfind.rb
|
42
|
-
- test/alltests.rb
|
43
|
-
- test/gentestfiles.rb
|
44
|
-
- test/ioextrastest.rb
|
45
|
-
- test/stdrubyexttest.rb
|
46
|
-
- test/zipfilesystemtest.rb
|
47
|
-
- test/ziprequiretest.rb
|
48
|
-
- test/ziptest.rb
|
49
|
-
- test/data/file1.txt
|
50
|
-
- test/data/file1.txt.deflatedData
|
51
|
-
- test/data/file2.txt
|
52
|
-
- test/data/notzippedruby.rb
|
53
|
-
- test/data/rubycode.zip
|
54
|
-
- test/data/rubycode2.zip
|
55
|
-
- test/data/testDirectory.bin
|
56
|
-
- test/data/zipWithDirs.zip
|
57
|
-
- lib/download_quizzes.rb
|
58
|
-
- lib/zip/ioextras.rb
|
59
|
-
- lib/zip/stdrubyext.rb
|
60
|
-
- lib/zip/tempfile_bugfixed.rb
|
61
|
-
- lib/zip/zip.rb
|
62
|
-
- lib/zip/zipfilesystem.rb
|
63
|
-
- lib/zip/ziprequire.rb
|
64
|
-
- lib/quiz1/t/solutions/Bill Guindon/solitaire.rb
|
65
|
-
- lib/quiz1/t/solutions/Carlos/solitaire.rb
|
66
|
-
- lib/quiz1/t/solutions/Dennis Ranke/solitaire.rb
|
67
|
-
- lib/quiz1/t/solutions/Florian Gross/solitaire.rb
|
68
|
-
- lib/quiz1/t/solutions/Glen M. Lewis/solitaire.rb
|
69
|
-
- lib/quiz1/t/solutions/James Edward Gray II/solitaire.rb
|
70
|
-
- lib/quiz1/t/solutions/Jamis Buck/bin/main.rb
|
71
|
-
- lib/quiz1/t/solutions/Jamis Buck/lib/cipher.rb
|
72
|
-
- lib/quiz1/t/solutions/Jamis Buck/lib/cli.rb
|
73
|
-
- lib/quiz1/t/solutions/Jamis Buck/test/tc_deck.rb
|
74
|
-
- lib/quiz1/t/solutions/Jamis Buck/test/tc_key-stream.rb
|
75
|
-
- lib/quiz1/t/solutions/Jamis Buck/test/tc_keying-algorithms.rb
|
76
|
-
- lib/quiz1/t/solutions/Jamis Buck/test/tc_solitaire-cipher.rb
|
77
|
-
- lib/quiz1/t/solutions/Jamis Buck/test/tc_unkeyed-algorithm.rb
|
78
|
-
- lib/quiz1/t/solutions/Jamis Buck/test/tests.rb
|
79
|
-
- lib/quiz1/t/solutions/Jim Menard/solitaire_cypher.rb
|
80
|
-
- lib/quiz1/t/solutions/Jim Menard/test.rb
|
81
|
-
- lib/quiz1/t/solutions/Moses Hohman/cipher.rb
|
82
|
-
- lib/quiz1/t/solutions/Moses Hohman/deck.rb
|
83
|
-
- lib/quiz1/t/solutions/Moses Hohman/solitaire.rb
|
84
|
-
- lib/quiz1/t/solutions/Moses Hohman/test_cipher.rb
|
85
|
-
- lib/quiz1/t/solutions/Moses Hohman/test_deck.rb
|
86
|
-
- lib/quiz1/t/solutions/Moses Hohman/test_util.rb
|
87
|
-
- lib/quiz1/t/solutions/Moses Hohman/testsuite.rb
|
88
|
-
- lib/quiz1/t/solutions/Moses Hohman/util.rb
|
89
|
-
- lib/quiz1/t/solutions/Niklas Frykholm/solitaire.rb
|
90
|
-
- lib/quiz1/t/solutions/Thomas Leitner/solitaire.rb
|
91
|
-
test_files: []
|
92
|
-
rdoc_options: []
|
93
|
-
extra_rdoc_files: []
|
94
|
-
executables: []
|
95
|
-
extensions: []
|
96
77
|
requirements: []
|
97
|
-
|
78
|
+
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.3.1
|
81
|
+
signing_key:
|
82
|
+
specification_version: 2
|
83
|
+
summary: rubyzip is a ruby module for reading and writing zip files
|
84
|
+
test_files: []
|
85
|
+
|
data/lib/download_quizzes.rb
DELETED
@@ -1,119 +0,0 @@
|
|
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
|
-
}
|
@@ -1,205 +0,0 @@
|
|
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
|