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.

Files changed (54) hide show
  1. data/ChangeLog +92 -450
  2. data/NEWS +18 -0
  3. data/README +1 -1
  4. data/Rakefile +14 -13
  5. data/install.rb +4 -3
  6. data/lib/zip/ioextras.rb +11 -1
  7. data/lib/zip/stdrubyext.rb +0 -0
  8. data/lib/zip/tempfile_bugfixed.rb +0 -0
  9. data/lib/zip/zip.rb +57 -24
  10. data/lib/zip/zipfilesystem.rb +1 -0
  11. data/lib/zip/ziprequire.rb +0 -0
  12. data/samples/example.rb +0 -0
  13. data/samples/example_filesystem.rb +0 -1
  14. data/samples/gtkRubyzip.rb +0 -0
  15. data/samples/qtzip.rb +0 -0
  16. data/samples/write_simple.rb +0 -0
  17. data/samples/zipfind.rb +0 -0
  18. data/test/alltests.rb +0 -0
  19. data/test/data/notzippedruby.rb +0 -0
  20. data/test/gentestfiles.rb +0 -0
  21. data/test/ioextrastest.rb +0 -0
  22. data/test/stdrubyexttest.rb +0 -0
  23. data/test/zipfilesystemtest.rb +14 -4
  24. data/test/ziprequiretest.rb +0 -0
  25. data/test/ziptest.rb +30 -9
  26. metadata +76 -88
  27. data/lib/download_quizzes.rb +0 -119
  28. data/lib/quiz1/t/solutions/Bill Guindon/solitaire.rb +0 -205
  29. data/lib/quiz1/t/solutions/Carlos/solitaire.rb +0 -111
  30. data/lib/quiz1/t/solutions/Dennis Ranke/solitaire.rb +0 -111
  31. data/lib/quiz1/t/solutions/Florian Gross/solitaire.rb +0 -301
  32. data/lib/quiz1/t/solutions/Glen M. Lewis/solitaire.rb +0 -268
  33. data/lib/quiz1/t/solutions/James Edward Gray II/solitaire.rb +0 -132
  34. data/lib/quiz1/t/solutions/Jamis Buck/bin/main.rb +0 -13
  35. data/lib/quiz1/t/solutions/Jamis Buck/lib/cipher.rb +0 -230
  36. data/lib/quiz1/t/solutions/Jamis Buck/lib/cli.rb +0 -24
  37. data/lib/quiz1/t/solutions/Jamis Buck/test/tc_deck.rb +0 -30
  38. data/lib/quiz1/t/solutions/Jamis Buck/test/tc_key-stream.rb +0 -19
  39. data/lib/quiz1/t/solutions/Jamis Buck/test/tc_keying-algorithms.rb +0 -31
  40. data/lib/quiz1/t/solutions/Jamis Buck/test/tc_solitaire-cipher.rb +0 -66
  41. data/lib/quiz1/t/solutions/Jamis Buck/test/tc_unkeyed-algorithm.rb +0 -17
  42. data/lib/quiz1/t/solutions/Jamis Buck/test/tests.rb +0 -2
  43. data/lib/quiz1/t/solutions/Jim Menard/solitaire_cypher.rb +0 -204
  44. data/lib/quiz1/t/solutions/Jim Menard/test.rb +0 -47
  45. data/lib/quiz1/t/solutions/Moses Hohman/cipher.rb +0 -97
  46. data/lib/quiz1/t/solutions/Moses Hohman/deck.rb +0 -140
  47. data/lib/quiz1/t/solutions/Moses Hohman/solitaire.rb +0 -14
  48. data/lib/quiz1/t/solutions/Moses Hohman/test_cipher.rb +0 -68
  49. data/lib/quiz1/t/solutions/Moses Hohman/test_deck.rb +0 -146
  50. data/lib/quiz1/t/solutions/Moses Hohman/test_util.rb +0 -38
  51. data/lib/quiz1/t/solutions/Moses Hohman/testsuite.rb +0 -5
  52. data/lib/quiz1/t/solutions/Moses Hohman/util.rb +0 -27
  53. data/lib/quiz1/t/solutions/Niklas Frykholm/solitaire.rb +0 -151
  54. data/lib/quiz1/t/solutions/Thomas Leitner/solitaire.rb +0 -198
File without changes
@@ -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
- File.copy(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
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
- File.copy(TestZipFile::TEST_ZIP2.zip_name, TEST_ZIP.zip_name)
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
- newName = "changed name"
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
- zfRead.close
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
- File.copy(TestFiles::RANDOM_ASCII_FILE1, "okToDelete.txt")
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.move("okToDelete.txt", "okToDeleteMoved.txt")
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.1
7
- date: 2006-07-29
8
- summary: rubyzip is a ruby module for reading and writing zip files
9
- require_paths:
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
- required_ruby_version: !ruby/object:Gem::Version::Requirement
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
- - !ruby/object:Gem::Version
24
- version: 0.0.0
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
- dependencies: []
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
+
@@ -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