aalib-ruby 0.7.1

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.
@@ -0,0 +1,95 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ Spec::Runner.configure do |config|
4
+ config.before :each do
5
+ @aa = AAlib.init(AAlib.memory_driver)
6
+ end
7
+
8
+ config.after :each do
9
+ @aa.close if @aa
10
+ end
11
+ end
12
+
13
+ describe "AAlib::Context#mulx" do
14
+ it "returns the ratio of image and screen widths" do
15
+ @aa.mulx.should == @aa.imgwidth / @aa.scrwidth
16
+ end
17
+ end
18
+
19
+ describe "AAlib::Context#muly" do
20
+ it "returns the ratio of image and screen heights" do
21
+ @aa.mulx.should == @aa.imgwidth / @aa.scrwidth
22
+ end
23
+ end
24
+
25
+ describe "AAlib::Context#imgwidth" do
26
+ it "returns the width of the image buffer" do
27
+ hp = AAlib::HardwareParams.new
28
+ hp.width = 100
29
+ aa = AAlib.init(AAlib.memory_driver, hp)
30
+ begin
31
+ aa.imgwidth.should == 100 * aa.mulx
32
+ ensure
33
+ aa.close
34
+ end
35
+ end
36
+ end
37
+
38
+ describe "AAlib::Context#imgheight" do
39
+ it "returns the width of the image buffer" do
40
+ hp = AAlib::HardwareParams.new
41
+ hp.height = 100
42
+ aa = AAlib.init(AAlib.memory_driver, hp)
43
+ begin
44
+ aa.imgheight.should == 100 * aa.muly
45
+ ensure
46
+ aa.close
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "AAlib::Context#render" do
52
+ it "raises TypeError with wrong render_params" do
53
+ lambda { @aa.render(Object.new) }.should raise_error(TypeError)
54
+ end
55
+ end
56
+
57
+ describe "AAlib::Context#putpixel" do
58
+ it "puts a pixel to the image buffer" do
59
+ 50.times do
60
+ color = rand(256)
61
+ x = rand(@aa.imgwidth)
62
+ y = rand(@aa.imgheight)
63
+ @aa.putpixel(x, y, color)
64
+ @aa.image[y*@aa.imgwidth + x].should == color
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "AAlib::Context#copy_image_from" do
70
+ before :each do
71
+ @aa1 = AAlib.init(AAlib.memory_driver)
72
+ @aa2 = AAlib.init(AAlib.memory_driver)
73
+ end
74
+
75
+ after :each do
76
+ @aa1.close
77
+ @aa2.close
78
+ end
79
+
80
+ it "copies the image buffer from another AAlib::Context" do
81
+ pixels = Hash.new
82
+ 100.times do
83
+ x = rand(@aa2.imgwidth)
84
+ y = rand(@aa2.imgheight)
85
+ color = rand(256)
86
+ @aa2.putpixel(x, y, color)
87
+ pixels[[x,y]] = color
88
+ end
89
+
90
+ @aa1.copy_image_from(@aa2)
91
+ pixels.each do |xy, color|
92
+ @aa1.image[@aa1.imgwidth*xy[1] + xy[0]].should == color
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,89 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'aalib'
3
+
4
+ describe "AAlib::SaveFormat.find" do
5
+ it "finds formats when given the full formatname" do
6
+ format = AAlib::SaveFormat.find("Text file")
7
+ format.should be_an_instance_of(AAlib::SaveFormat)
8
+ format.formatname.should == "Text file"
9
+ format.extension.should == ".txt"
10
+
11
+ format = AAlib::SaveFormat.find("Pure html")
12
+ format.should be_an_instance_of(AAlib::SaveFormat)
13
+ format.formatname.should == "Pure html"
14
+ format.extension.should == ".html"
15
+
16
+ ## NOTE: the "seqences" typo are hard coded into AA-lib v 1.4
17
+ format = AAlib::SaveFormat.find("ANSI escape seqences")
18
+ format.should be_an_instance_of(AAlib::SaveFormat)
19
+ format.formatname.should == "ANSI escape seqences"
20
+ format.extension.should == ".ansi"
21
+ end
22
+
23
+ it "finds formats when given the partial formatname" do
24
+ format = AAlib::SaveFormat.find("Text")
25
+ format.should be_an_instance_of(AAlib::SaveFormat)
26
+ format.formatname.should == "Text file"
27
+ format.extension.should == ".txt"
28
+
29
+ format = AAlib::SaveFormat.find("html")
30
+ format.should be_an_instance_of(AAlib::SaveFormat)
31
+ format.formatname.should == "Pure html"
32
+ format.extension.should == ".html"
33
+
34
+ format = AAlib::SaveFormat.find("ANSI")
35
+ format.should be_an_instance_of(AAlib::SaveFormat)
36
+ format.formatname.should == "ANSI escape seqences"
37
+ format.extension.should == ".ansi"
38
+ end
39
+
40
+ it "finds formats ignoring case" do
41
+ format = AAlib::SaveFormat.find("tEXT")
42
+ format.should be_an_instance_of(AAlib::SaveFormat)
43
+ format.formatname.should == "Text file"
44
+ format.extension.should == ".txt"
45
+
46
+ format = AAlib::SaveFormat.find("HTML")
47
+ format.should be_an_instance_of(AAlib::SaveFormat)
48
+ format.formatname.should == "Pure html"
49
+ format.extension.should == ".html"
50
+
51
+ format = AAlib::SaveFormat.find("ansi")
52
+ format.should be_an_instance_of(AAlib::SaveFormat)
53
+ format.formatname.should == "ANSI escape seqences"
54
+ format.extension.should == ".ansi"
55
+ end
56
+
57
+ it "finds formats when given a Regexp" do
58
+ format = AAlib::SaveFormat.find(/text/i)
59
+ format.should be_an_instance_of(AAlib::SaveFormat)
60
+ format.formatname.should == "Text file"
61
+ format.extension.should == ".txt"
62
+
63
+ format = AAlib::SaveFormat.find(/HP.*big/)
64
+ format.should be_an_instance_of(AAlib::SaveFormat)
65
+ format.formatname.should == "HP laser jet - A4 big font"
66
+ format.extension.should == ".hp"
67
+
68
+ format = AAlib::SaveFormat.find(/IRC.*II/)
69
+ format.should be_an_instance_of(AAlib::SaveFormat)
70
+ format.formatname.should == "For catting to an IRC channel II"
71
+ format.extension.should == ".irc"
72
+ end
73
+ end
74
+
75
+ describe "AAlib::SaveFormat.formatname" do
76
+ it "returns the formatname" do
77
+ format = AAlib::SaveFormat.find("text")
78
+ format.should be_an_instance_of(AAlib::SaveFormat)
79
+ format.formatname.should == "Text file"
80
+ end
81
+ end
82
+
83
+ describe "AAlib::SaveFormat.extension" do
84
+ it "returns the file extension including the dot" do
85
+ format = AAlib::SaveFormat.find("text")
86
+ format.should be_an_instance_of(AAlib::SaveFormat)
87
+ format.extension.should == ".txt"
88
+ end
89
+ end
@@ -0,0 +1,34 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'aalib'
3
+
4
+ describe "The save procedure" do
5
+ before :each do
6
+ @file = File.join(File.dirname(__FILE__), "scratch", "test_save")
7
+ end
8
+
9
+ after :each do
10
+ # File.delete(@file) if File.exists?(@file)
11
+ end
12
+
13
+ it "saves a graphics context as text using the save driver" do
14
+ format = AAlib::SaveFormat.find("text")
15
+ data = AAlib::SaveData.new(@file, format)
16
+
17
+ hp = AAlib::HardwareParams.new
18
+ rp = AAlib::RenderParams.new
19
+
20
+ context = AAlib.init(AAlib.save_driver, hp, data)
21
+ draw_diagonal_gradient(context)
22
+ context.render(rp)
23
+ puts_hello_world(context)
24
+ context.flush
25
+
26
+ context.close
27
+
28
+ efile = File.join(File.dirname(__FILE__), "hello_world.txt")
29
+ expected = File.open(efile) { |f| f.read }
30
+ result = File.open(@file) { |f| f.read }
31
+
32
+ result.should == expected
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'aalib'
3
+
4
+ describe "AAlib::SaveData.new" do
5
+ it "Creates a new instance of SaveData" do
6
+ file = "file.txt"
7
+ data = AAlib::SaveData.new(file, "text")
8
+ data.should be_an_instance_of(AAlib::SaveData)
9
+ data.name.should == "file.txt"
10
+ end
11
+
12
+ it "Uses AAlib::SaveFormat.find when given a string format name" do
13
+ file = "file.txt"
14
+ data = AAlib::SaveData.new(file, "text")
15
+ data.should be_an_instance_of(AAlib::SaveData)
16
+ data.name.should == file
17
+ data.format.should == AAlib::SaveFormat.find("text")
18
+ end
19
+
20
+ it "Uses AAlib::SaveFormat.find when given a regexp format name" do
21
+ file = "file.txt"
22
+ data = AAlib::SaveData.new(file, /text/i)
23
+ data.should be_an_instance_of(AAlib::SaveData)
24
+ data.name.should == file
25
+ data.format.should == AAlib::SaveFormat.find(/text/i)
26
+ end
27
+ end
@@ -0,0 +1,168 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require 'aalib'
3
+
4
+ describe "AAlib.autoinit" do
5
+ # We can't check this so much because it might initialize Curses on our terminal
6
+ #
7
+ it "raises TypeError with wrong hardware_params" do
8
+ clo = lambda { AAlib.autoinit(Object.new) }
9
+ clo.should raise_error(TypeError)
10
+ end
11
+ end
12
+
13
+ describe "AAlib.init" do
14
+ before :each do
15
+ @hp = AAlib::HardwareParams.new
16
+ end
17
+
18
+ # AAlib.init checks its arguments in violation of duck typing, but incorrect
19
+ # arguments can lead to segmentation faults if AAlib calls the C-library
20
+ # functions with incorrect arguments.
21
+
22
+ it "raises TypeError with wrong driver" do
23
+ clo = lambda { AAlib.init(Object.new) }
24
+ clo.should raise_error(TypeError)
25
+ end
26
+
27
+ it "raises TypeError with wrong hardware_params" do
28
+ clo = lambda { AAlib.init(AAlib.memory_driver, Object.new) }
29
+ clo.should raise_error(TypeError)
30
+ end
31
+
32
+ it "returns an AAlib::Context with memory driver" do
33
+ AAlib.init(AAlib.memory_driver, @hp).should be_an_instance_of(AAlib::Context)
34
+ end
35
+
36
+ it "returns an AAlib::Context with memory driver and no hardware_params" do
37
+ AAlib.init(AAlib.memory_driver).should be_an_instance_of(AAlib::Context)
38
+ end
39
+
40
+ it "returns an AAlib::Context when called with save driver" do
41
+ opts = AAlib::SaveData.new("test.txt", "text")
42
+ context = AAlib.init(AAlib.save_driver, @hp, opts)
43
+ context.should be_an_instance_of(AAlib::Context)
44
+ end
45
+
46
+ it "raises ArgumentError when called with save driver and no driver_opts" do
47
+ clo = lambda { AAlib.init(AAlib.save_driver, @hp, nil) }
48
+ clo.should raise_error(ArgumentError)
49
+ end
50
+
51
+ it "raises TypeError when called with save driver and wrong driver_opts" do
52
+ opts = AAlib::SaveFormat.find("text")
53
+ clo = lambda { AAlib.init(AAlib.save_driver, @hp, opts) }
54
+ clo.should raise_error(TypeError)
55
+ end
56
+ end
57
+
58
+ # describe "AAlib.color_from_rgb" do
59
+ # it "converts an RGB color to greyscale" do
60
+ # AAlib.color_from_rgb(0, 0, 0).should == 0
61
+ # AAlib.color_from_rgb(255, 255, 255).should == 255
62
+ # AAlib.color_from_rgb(255, 0, 0).should == 29
63
+ # AAlib.color_from_rgb(0, 255, 0).should == 58
64
+ # AAlib.color_from_rgb(0, 0, 255).should == 10
65
+ # AAlib.color_from_rgb(47, 57, 98).should == 22
66
+ # end
67
+ #
68
+ # it "behaves stupidly when args are larger than 255" do
69
+ # AAlib.color_from_rgb(256, 0, 0).should == 30
70
+ # end
71
+ # end
72
+
73
+ describe "AAlib.help" do
74
+ it "returns a large help string" do
75
+ AAlib.help.should be_an_instance_of(String)
76
+ end
77
+ end
78
+
79
+ describe "AAlib.formats" do
80
+ it "returns an array of formats" do
81
+ AAlib.formats.should be_an_instance_of(Array)
82
+ end
83
+
84
+ it "returns an array of AAlib::SaveFormat objects" do
85
+ AAlib.formats.each do |driver|
86
+ driver.should be_an_instance_of(AAlib::SaveFormat)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "AAlib.drivers" do
92
+ it "returns an array of drivers" do
93
+ AAlib.drivers.should be_an_instance_of(Array)
94
+ end
95
+
96
+ it "returns an array of AAlib::Driver objects" do
97
+ AAlib.drivers.each do |driver|
98
+ driver.should be_an_instance_of(AAlib::Driver)
99
+ end
100
+ end
101
+ end
102
+
103
+ describe "AAlib.save_driver" do
104
+ it "returns the driver to use for saving to disk" do
105
+ driver = AAlib.save_driver
106
+ driver.should be_an_instance_of(AAlib::Driver)
107
+ driver.shortname.should == 'save'
108
+ driver.name.should == 'Special driver for saving to files'
109
+ end
110
+ end
111
+
112
+ describe "AAlib.memory_driver" do
113
+ it "returns the driver to use for an in-memory context" do
114
+ driver = AAlib.memory_driver
115
+ driver.should be_an_instance_of(AAlib::Driver)
116
+ driver.shortname.should == 'mem'
117
+ # FIXME: may depend on AA-lib version?
118
+ driver.name.should == 'Dummy memory driver 1.0'
119
+ end
120
+ end
121
+
122
+ describe "AAlib.parseoptions" do
123
+ before :each do
124
+ @hp = AAlib::HardwareParams.new
125
+ @rp = AAlib::RenderParams.new
126
+ end
127
+
128
+ it "parses commandline options, setting values in RenderParams" do
129
+ argv = %w{-gamma 2.0 -contrast 5 -bright 100}
130
+ AAlib.parseoptions(@hp, @rp, argv).should be_true
131
+ @rp.gamma.should be_close(2.0, 0.01)
132
+ @rp.contrast.should == 5
133
+ @rp.bright.should == 100
134
+ end
135
+
136
+ it "parses commandline options, setting values in HardwareParams" do
137
+ argv = %w{-width 101 -height 57}
138
+ AAlib.parseoptions(@hp, @rp, argv).should be_true
139
+ @hp.width.should == 101
140
+ @hp.height.should == 57
141
+ end
142
+
143
+ it "leaves untouched other options" do
144
+ argv = %w{--verbose -gamma 2.0 -contrast 5 -bright 100 -other-option 70}
145
+ AAlib.parseoptions(@hp, @rp, argv).should be_true
146
+ argv.should == %w{--verbose -other-option 70}
147
+ end
148
+
149
+ it "uses ARGV by default" do
150
+ ARGV.replace %w{--verbose -gamma 2.0 -contrast 5 -bright 100 -other-option 70}
151
+ AAlib.parseoptions(@hp, @rp).should be_true
152
+ ARGV.should == %w{--verbose -other-option 70}
153
+
154
+ @rp.gamma.should be_close(2.0, 0.01)
155
+ @rp.contrast.should == 5
156
+ @rp.bright.should == 100
157
+ end
158
+
159
+ it "raises TypeError with wrong hardware_params" do
160
+ clo = lambda { AAlib.parseoptions(Object.new, @rp) }
161
+ clo.should raise_error(TypeError)
162
+ end
163
+
164
+ it "raises TypeError with wrong hardware_params" do
165
+ clo = lambda { AAlib.parseoptions(@hp, Object.new) }
166
+ clo.should raise_error(TypeError)
167
+ end
168
+ end
@@ -0,0 +1,25 @@
1
+ . . ........-.:.::::::::;:;;;=;=======+++++|+|+|||||||||i|iiiiiiilllllIIIvIv
2
+ . . .........:-::-:::::::;;;;=;=======++++++|+|+|||+|||||ii|iiiiiillllllIIvIvvv
3
+ . .........-:-:.::::::::;;;;=========++++|+||+||||+|||||ii|iiiiiilllllIIvIvvvvvv
4
+ ........:.::.::::::::;;;=;========++|+|+|+|+||||||||iiiiiiiiillllllIIvvIvvvvvvnv
5
+ ....--::-::::::::;;;=;=========++|+++|+|+|||||||||iii|iiiillllllIvvvvvvvvvvnvnnn
6
+ .--:-:-:::::::;;;=;=;======+++|+|=|||+|||||||||i|iiiiilillllIIvIvvIvvvvvnnnnnnnn
7
+ ::-::::::::;;;=;========+++|+|++||+||||||||i|iiiiiiillllIIIvIvvvvvvvvnnnnnnnnooo
8
+ :-::::::;;;=;========++|++|++|+|||||||||iiiiiiiillllllIIvIvvvvvvvnvnnnnnnnnoo222
9
+ :::::;;;=;========++|+++|+|||||||||||i|iiiiiilllllIIvIvvvvvvvvnvnnnnnnnooo22222S
10
+ ;:;=;=;=======+++|+++|||+|||||||||iiiiiiiiillllIIvIvvvvvvvvnvnnnnnnooo2o2222S2S2
11
+ ;=;========+++++|=|||+|+|||||||iiiiiiiilllIlIIvIvvvvvvvvnvnnnnnnoooo2222S2SS2XSX
12
+ ========+++|+|+|+||+||| nnnnoooo2o2S22S2S2SSSSSX
13
+ =====+++|+|++|+|||||||| AA-lib: the ascii-art library noooo2oSoS22SS2XSSXSXXXX
14
+ =++++|+|++|+|||||||||ii oo2222SoS2SSS2XXSXXXXXXZ
15
+ +++|+|+|+|||||||||iiiiiiiililIlIIvIvvvvvvvvvnnnnnnnnooo22222S2SSSSSSSXXXXXXXZZZU
16
+ |+|+|+||||||||i|iiiiiiiilllIIIvIvvvvvvvvvnnnnnnnooo2o22S2S2X2XS2XSXXXXXXZZZZ#Z#Z
17
+ |+|||||||||iiiiiiiiillllIIIvIvvvvvvvvnvnnnnnnoooo222S2S2S2SSSSSXXXXXXZZZZZ#ZUZ##
18
+ ||||||||iiiiiiiillllllIvIvvvvvvvvvnnnnnnnoooo2o2S22S2S2SSSXSXXXXXXZZZZZ#Z#Z#####
19
+ |||||iiiiiiiiilllllIvIvIvvvvvvvnnnnnnnnooo2222S22SS2XSSXXXXXXXXZZZZUZ#UZ########
20
+ i|iiiiiiiiilllllIIvvvvvvvvvnvnnnnnnnooo22222S2S2XS2XXSXXXXXXZZZUZ#Z#UUU########m
21
+ iiiiiiiilllIlIvvvvvvvvvvnnnnnnnnoooo2222S2SS2SSSSSXXXXXXXZZZUZ#Z#Z#########mmmBB
22
+ iiiillllIIIvvvIvvvvvvnvnnnnnnooo2o2S22S2S2X2XXSXXXXXXZZZZ#Z#Z#Z#########mmmBBWmW
23
+ llllllIIvIvvvvvvvvnnnnnnnnooo2oSoS22S2SSSSXXXXXXXXZZZZUZ#Z#Z#########mmmBBWBWmWW
24
+ lllIvIvvvvvvvvvnnnnnnnnoo2o222SoS2SSSSSSXXXXXXXZZZZ#Z#Z#U########mmmBmWBWBWmWWWW
25
+ vIvvIvvvvvvnvnnnnnnnooo2222S2S2SSSSSSXXXXXXXZZZZ#Z#Z#U########mmmBBBWBWmWWBWWWWW
@@ -0,0 +1,25 @@
1
+ . . ........-.:.::::::::;:;;;=;=======+++++|+|+|||||||||i|iiiiiiilllllIIIvIv
2
+ . . .........:-::-:::::::;;;;=;=======++++++|+|+|||+|||||ii|iiiiiillllllIIvIvvv
3
+ . .........-:-:.::::::::;;;;=========++++|+||+||||+|||||ii|iiiiiilllllIIvIvvvvvv
4
+ ........:.::.::::::::;;;=;========++|+|+|+|+||||||||iiiiiiiiillllllIIvvIvvvvvvnv
5
+ ....--::-::::::::;;;=;=========++|+++|+|+|||||||||iii|iiiillllllIvvvvvvvvvvnvnnn
6
+ .--:-:-:::::::;;;=;=;======+++|+|=|||+|||||||||i|iiiiilillllIIvIvvIvvvvvnnnnnnnn
7
+ ::-::::::::;;;=;========+++|+|++||+||||||||i|iiiiiiillllIIIvIvvvvvvvvnnnnnnnnooo
8
+ :-::::::;;;=;========++|++|++|+|||||||||iiiiiiiillllllIIvIvvvvvvvnvnnnnnnnnoo222
9
+ :::::;;;=;========++|+++|+|||||||||||i|iiiiiilllllIIvIvvvvvvvvnvnnnnnnnooo22222S
10
+ ;:;=;=;=======+++|+++|||+|||||||||iiiiiiiiillllIIvIvvvvvvvvnvnnnnnnooo2o2222S2S2
11
+ ;=;========+++++|=|||+|+|||||||iiiiiiiilllIlIIvIvvvvvvvvnvnnnnnnoooo2222S2SS2XSX
12
+ ========+++|+|+|+||+||| nnnnoooo2o2S22S2S2SSSSSX
13
+ =====+++|+|++|+|||||||| AA-lib: the ascii-art library noooo2oSoS22SS2XSSXSXXXX
14
+ =++++|+|++|+|||||||||ii oo2222SoS2SSS2XXSXXXXXXZ
15
+ +++|+|+|+|||||||||iiiiiiiililIlIIvIvvvvvvvvvnnnnnnnnooo22222S2SSSSSSSXXXXXXXZZZU
16
+ |+|+|+||||||||i|iiiiiiiilllIIIvIvvvvvvvvvnnnnnnnooo2o22S2S2X2XS2XSXXXXXXZZZZ#Z#Z
17
+ |+|||||||||iiiiiiiiillllIIIvIvvvvvvvvnvnnnnnnoooo222S2S2S2SSSSSXXXXXXZZZZZ#ZUZ##
18
+ ||||||||iiiiiiiillllllIvIvvvvvvvvvnnnnnnnoooo2o2S22S2S2SSSXSXXXXXXZZZZZ#Z#Z#####
19
+ |||||iiiiiiiiilllllIvIvIvvvvvvvnnnnnnnnooo2222S22SS2XSSXXXXXXXXZZZZUZ#UZ########
20
+ i|iiiiiiiiilllllIIvvvvvvvvvnvnnnnnnnooo22222S2S2XS2XXSXXXXXXZZZUZ#Z#UUU########m
21
+ iiiiiiiilllIlIvvvvvvvvvvnnnnnnnnoooo2222S2SS2SSSSSXXXXXXXZZZUZ#Z#Z#########mmmBB
22
+ iiiillllIIIvvvIvvvvvvnvnnnnnnooo2o2S22S2S2X2XXSXXXXXXZZZZ#Z#Z#Z#########mmmBBWmW
23
+ llllllIIvIvvvvvvvvnnnnnnnnooo2oSoS22S2SSSSXXXXXXXXZZZZUZ#Z#Z#########mmmBBWBWmWW
24
+ lllIvIvvvvvvvvvnnnnnnnnoo2o222SoS2SSSSSSXXXXXXXZZZZ#Z#Z#U########mmmBmWBWBWmWWWW
25
+ vIvvIvvvvvvnvnnnnnnnooo2222S2S2SSSSSSXXXXXXXZZZZ#Z#Z#U########mmmBBBWBWmWWBWWWWW