id3tag 0.8.0 → 0.9.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -46
  3. data/.travis.yml +6 -5
  4. data/id3tag.gemspec +8 -8
  5. data/lib/id3tag/audio_file.rb +24 -6
  6. data/lib/id3tag/id3_v2_tag_header.rb +4 -4
  7. data/lib/id3tag/number_util.rb +1 -0
  8. data/lib/id3tag/tag.rb +2 -2
  9. data/lib/id3tag/version.rb +1 -1
  10. data/spec/features/can_read_non_audio_files_spec.rb +8 -7
  11. data/spec/features/can_read_tag_v1_spec.rb +6 -6
  12. data/spec/lib/id3tag/audio_file_spec.rb +85 -15
  13. data/spec/lib/id3tag/frames/util/genre_name_by_id_finder_spec.rb +2 -2
  14. data/spec/lib/id3tag/frames/v1/comments_frame_spec.rb +7 -7
  15. data/spec/lib/id3tag/frames/v1/genre_frame_spec.rb +3 -3
  16. data/spec/lib/id3tag/frames/v1/text_frame_spec.rb +2 -2
  17. data/spec/lib/id3tag/frames/v1/track_nr_frame_spec.rb +3 -3
  18. data/spec/lib/id3tag/frames/v2/basic_frame_spec.rb +56 -16
  19. data/spec/lib/id3tag/frames/v2/comments_frame_spec.rb +5 -5
  20. data/spec/lib/id3tag/frames/v2/frame_fabricator_spec.rb +8 -8
  21. data/spec/lib/id3tag/frames/v2/frame_flags_spec.rb +539 -108
  22. data/spec/lib/id3tag/frames/v2/genre_frame/genre_parser_24_spec.rb +3 -3
  23. data/spec/lib/id3tag/frames/v2/genre_frame/genre_parser_pre_24_spec.rb +8 -8
  24. data/spec/lib/id3tag/frames/v2/genre_frame_spec.rb +9 -9
  25. data/spec/lib/id3tag/frames/v2/picture_frame_spec.rb +37 -17
  26. data/spec/lib/id3tag/frames/v2/text_frame_spec.rb +7 -7
  27. data/spec/lib/id3tag/frames/v2/unique_file_id_frame_spec.rb +4 -4
  28. data/spec/lib/id3tag/frames/v2/user_text_frame_spec.rb +19 -4
  29. data/spec/lib/id3tag/id3_v1_frame_parser_spec.rb +10 -10
  30. data/spec/lib/id3tag/id3_v2_frame_parser_spec.rb +6 -6
  31. data/spec/lib/id3tag/id3_v2_tag_header_spec.rb +105 -21
  32. data/spec/lib/id3tag/id3tag_spec.rb +1 -1
  33. data/spec/lib/id3tag/io_util_spec.rb +4 -4
  34. data/spec/lib/id3tag/number_util_spec.rb +10 -2
  35. data/spec/lib/id3tag/string_util_spec.rb +10 -10
  36. data/spec/lib/id3tag/synchsafe_integer_spec.rb +6 -6
  37. data/spec/lib/id3tag/tag_spec.rb +192 -91
  38. metadata +28 -29
  39. data/Gemfile.lock +0 -77
@@ -9,15 +9,15 @@ describe ID3Tag::Frames::V2::GenreFrame::GenreParser24 do
9
9
  context "when version is 2.4" do
10
10
  context "with remix and cover" do
11
11
  let(:genre_string) { "RX\x00CR" }
12
- it { should == ['Remix', 'Cover'] }
12
+ it { is_expected.to eq(['Remix', 'Cover']) }
13
13
  end
14
14
  context "with refinement and number" do
15
15
  let(:genre_string) { "ABC\x0017" }
16
- it { should == ['ABC', 'Rock'] }
16
+ it { is_expected.to eq(['ABC', 'Rock']) }
17
17
  end
18
18
  context "with one genre" do
19
19
  let(:genre_string) { "17" }
20
- it { should == ['Rock'] }
20
+ it { is_expected.to eq(['Rock']) }
21
21
  end
22
22
  end
23
23
 
@@ -9,39 +9,39 @@ describe ID3Tag::Frames::V2::GenreFrame::GenreParserPre24 do
9
9
  context "without refinements" do
10
10
  context "with one genre" do
11
11
  let(:genre_string) { '(17)' }
12
- it { should == ['Rock'] }
12
+ it { is_expected.to eq(['Rock']) }
13
13
  end
14
14
  context "with multiple genres" do
15
15
  let(:genre_string) { '(17)(18)' }
16
- it { should == ['Rock', 'Techno'] }
16
+ it { is_expected.to eq(['Rock', 'Techno']) }
17
17
  end
18
18
  context "with remix and cover" do
19
19
  let(:genre_string) { '(RX)(CR)' }
20
- it { should == ['Remix', 'Cover'] }
20
+ it { is_expected.to eq(['Remix', 'Cover']) }
21
21
  end
22
22
  end
23
23
  context "with refinements" do
24
24
  context "with one genre" do
25
25
  let(:genre_string) { '(17)qwerty' }
26
- it { should == ['qwerty'] }
26
+ it { is_expected.to eq(['qwerty']) }
27
27
  end
28
28
  context "with miltiple genres but only 1 refinement" do
29
29
  let(:genre_string) { '(0)(16)(17)qwerty' }
30
- it { should == ['Blues', 'Reggae', 'qwerty'] }
30
+ it { is_expected.to eq(['Blues', 'Reggae', 'qwerty']) }
31
31
  end
32
32
  context "with multiple genres" do
33
33
  let(:genre_string) { '(17)qwerty(18)abcdef' }
34
- it { should == ['qwerty', 'abcdef'] }
34
+ it { is_expected.to eq(['qwerty', 'abcdef']) }
35
35
  end
36
36
  end
37
37
  context "with refinement containing '('" do
38
38
  context "with one genre" do
39
39
  let(:genre_string) { '(55)((I think...)' }
40
- it { should == ['(I think...)'] }
40
+ it { is_expected.to eq(['(I think...)']) }
41
41
  end
42
42
  context "with multiple genres" do
43
43
  let(:genre_string) { '(55)((I think...)(17)' }
44
- it { should == ['(I think...)', 'Rock'] }
44
+ it { is_expected.to eq(['(I think...)', 'Rock']) }
45
45
  end
46
46
  end
47
47
  end
@@ -10,7 +10,7 @@ describe ID3Tag::Frames::V2::GenreFrame do
10
10
 
11
11
  describe '#id' do
12
12
  subject { frame.id }
13
- it { should == :TCON }
13
+ it { is_expected.to eq(:TCON) }
14
14
  end
15
15
 
16
16
  describe '#content' do
@@ -21,26 +21,26 @@ describe ID3Tag::Frames::V2::GenreFrame do
21
21
 
22
22
  context "when one genre" do
23
23
  before do
24
- ID3Tag::Frames::V2::GenreFrame::GenreParserPre24.any_instance.stub(:genres) { ['A'] }
24
+ allow_any_instance_of(ID3Tag::Frames::V2::GenreFrame::GenreParserPre24).to receive(:genres) { ['A'] }
25
25
  end
26
26
 
27
- it { should eq('A') }
27
+ it { is_expected.to eq('A') }
28
28
  end
29
29
  context "when two genres" do
30
30
  before do
31
- ID3Tag::Frames::V2::GenreFrame::GenreParserPre24.any_instance.stub(:genres) { ['A', 'B'] }
31
+ allow_any_instance_of(ID3Tag::Frames::V2::GenreFrame::GenreParserPre24).to receive(:genres) { ['A', 'B'] }
32
32
  end
33
33
 
34
- it { should eq('A, B') }
34
+ it { is_expected.to eq('A, B') }
35
35
  end
36
36
  end
37
37
 
38
38
  context "when tag major version is 4" do
39
39
  let(:major_version_number) { 4 }
40
40
  before do
41
- ID3Tag::Frames::V2::GenreFrame::GenreParser24.any_instance.stub(:genres) { ['B'] }
41
+ allow_any_instance_of(ID3Tag::Frames::V2::GenreFrame::GenreParser24).to receive(:genres) { ['B'] }
42
42
  end
43
- it { should eq('B') }
43
+ it { is_expected.to eq('B') }
44
44
  end
45
45
  context "when tag major version is 232" do
46
46
  let(:major_version_number) { 232 }
@@ -52,11 +52,11 @@ describe ID3Tag::Frames::V2::GenreFrame do
52
52
 
53
53
  describe '#inspect' do
54
54
  before do
55
- frame.stub(:content) { 'Rock' }
55
+ allow(frame).to receive(:content) { 'Rock' }
56
56
  end
57
57
 
58
58
  it 'should be pretty inspectable' do
59
- frame.inspect.should eq('<ID3Tag::Frames::V2::GenreFrame TCON: Rock>')
59
+ expect(frame.inspect).to eq('<ID3Tag::Frames::V2::GenreFrame TCON: Rock>')
60
60
  end
61
61
  end
62
62
  end
@@ -22,36 +22,36 @@ describe ID3Tag::Frames::V2::PictureFrame do
22
22
 
23
23
  describe '#id' do
24
24
  subject { frame.id }
25
- it { should == :PIC }
25
+ it { is_expected.to eq(:PIC) }
26
26
  end
27
27
 
28
28
  describe "mime_type" do
29
29
  subject { frame.mime_type }
30
- it { should eq('image/png') }
30
+ it { is_expected.to eq('image/png') }
31
31
  context "when mime type is blank" do
32
32
  let(:format) { "\x00\x00\x00" }
33
- it { should eq('image/') }
33
+ it { is_expected.to eq('image/') }
34
34
  end
35
35
  end
36
36
 
37
37
  describe "#data" do
38
38
  subject { frame.data }
39
- it { should == "picture data" }
39
+ it { is_expected.to eq("picture data") }
40
40
  end
41
41
 
42
42
  describe "#type" do
43
43
  subject { frame.type }
44
- it { should == :cover_front }
44
+ it { is_expected.to eq(:cover_front) }
45
45
  end
46
46
 
47
47
  describe "#description" do
48
48
  subject { frame.description }
49
- it { should == "picture description" }
49
+ it { is_expected.to eq("picture description") }
50
50
  end
51
51
 
52
52
  describe "#content" do
53
53
  subject { frame.content }
54
- it { should == "picture data" }
54
+ it { is_expected.to eq("picture data") }
55
55
  end
56
56
  end
57
57
 
@@ -66,42 +66,62 @@ describe ID3Tag::Frames::V2::PictureFrame do
66
66
 
67
67
  describe '#id' do
68
68
  subject { frame.id }
69
- it { should == :APIC }
69
+ it { is_expected.to eq(:APIC) }
70
70
  end
71
71
 
72
72
  describe "#data" do
73
73
  subject { frame.data }
74
- it { should == "picture data" }
74
+ it { is_expected.to eq("picture data") }
75
75
  end
76
76
 
77
77
  describe "#type" do
78
78
  subject { frame.type }
79
- it { should == :cover_front }
79
+ it { is_expected.to eq(:cover_front) }
80
80
  end
81
81
 
82
82
  describe "#mime_type" do
83
83
  subject { frame.mime_type }
84
- it { should == "image/png" }
84
+ it { is_expected.to eq("image/png") }
85
+ context "when mime type is omitted" do
86
+ let(:mime_type) { "\x00" }
87
+ subject { frame.mime_type }
88
+ it { is_expected.to eq("image/") }
89
+ end
85
90
  end
86
91
 
87
92
  describe "#description" do
88
93
  subject { frame.description }
89
- it { should == "picture description" }
94
+ it { is_expected.to eq("picture description") }
90
95
  end
91
96
 
92
97
  describe "#content" do
93
98
  subject { frame.content }
94
- it { should == "picture data" }
99
+ it { is_expected.to eq("picture data") }
95
100
  end
96
101
 
97
102
  context "when frame contains link not actual image data" do
98
103
  let(:raw_content) { "\x02-->\x00\x08\u0000a\u0000b\u0000c" }
99
104
  subject { frame }
100
105
 
101
- its(:link?) { should be_true }
102
- its(:mime_type) { should eq("-->") }
103
- its(:description) { should eq("abc") }
104
- its(:type) { should eq(:artist) }
106
+ describe '#link?' do
107
+ subject { super().link? }
108
+ it { is_expected.to eq(true) }
109
+ end
110
+
111
+ describe '#mime_type' do
112
+ subject { super().mime_type }
113
+ it { is_expected.to eq("-->") }
114
+ end
115
+
116
+ describe '#description' do
117
+ subject { super().description }
118
+ it { is_expected.to eq("abc") }
119
+ end
120
+
121
+ describe '#type' do
122
+ subject { super().type }
123
+ it { is_expected.to eq(:artist) }
124
+ end
105
125
  end
106
126
  end
107
127
  end
@@ -14,7 +14,7 @@ describe ID3Tag::Frames::V2::TextFrame do
14
14
 
15
15
  describe '#id' do
16
16
  subject { frame.id }
17
- it { should == :artist }
17
+ it { is_expected.to eq(:artist) }
18
18
  end
19
19
 
20
20
  describe '#content' do
@@ -24,7 +24,7 @@ describe ID3Tag::Frames::V2::TextFrame do
24
24
  let(:target_encoding) { Encoding::UTF_8 }
25
25
  let(:encoding_byte) { "\x03" }
26
26
  let(:text) { "Glāzšķūņrūķīši\x00" }
27
- it { should == 'Glāzšķūņrūķīši' }
27
+ it { is_expected.to eq('Glāzšķūņrūķīši') }
28
28
  end
29
29
 
30
30
  context "when encoding byte is not present" do
@@ -36,25 +36,25 @@ describe ID3Tag::Frames::V2::TextFrame do
36
36
  let(:target_encoding) { Encoding::ISO8859_1 }
37
37
  let(:encoding_byte) { "\x00" }
38
38
  let(:text) { "some fancy artist" }
39
- it { should == 'some fancy artist' }
39
+ it { is_expected.to eq('some fancy artist') }
40
40
  end
41
41
 
42
42
  context "when encoding is UTF_16" do
43
43
  let(:target_encoding) { Encoding::UTF_16 }
44
44
  let(:encoding_byte) { "\x01" }
45
- it { should == 'Glāzšķūņrūķīši' }
45
+ it { is_expected.to eq('Glāzšķūņrūķīši') }
46
46
  end
47
47
 
48
48
  context "when encoding is UTF_16BE" do
49
49
  let(:target_encoding) { Encoding::UTF_16BE }
50
50
  let(:encoding_byte) { "\x02" }
51
- it { should == 'Glāzšķūņrūķīši' }
51
+ it { is_expected.to eq('Glāzšķūņrūķīši') }
52
52
  end
53
53
 
54
54
  context "when encoding is UTF_8" do
55
55
  let(:target_encoding) { Encoding::UTF_8 }
56
56
  let(:encoding_byte) { "\x03" }
57
- it { should == 'Glāzšķūņrūķīši' }
57
+ it { is_expected.to eq('Glāzšķūņrūķīši') }
58
58
  end
59
59
 
60
60
  context "when UTF-16 and missing BOM" do
@@ -83,7 +83,7 @@ describe ID3Tag::Frames::V2::TextFrame do
83
83
 
84
84
  describe '#inspect' do
85
85
  it 'should be pretty inspectable' do
86
- frame.inspect.should eq('<ID3Tag::Frames::V2::TextFrame artist: Glāzšķūņrūķīši>')
86
+ expect(frame.inspect).to eq('<ID3Tag::Frames::V2::TextFrame artist: Glāzšķūņrūķīši>')
87
87
  end
88
88
  end
89
89
  end
@@ -10,22 +10,22 @@ describe ID3Tag::Frames::V2::UniqueFileIdFrame do
10
10
 
11
11
  describe '#id' do
12
12
  subject { frame.id }
13
- it { should == :UFID }
13
+ it { is_expected.to eq(:UFID) }
14
14
  end
15
15
 
16
16
  describe '#owner_identifier' do
17
17
  subject { frame.owner_identifier }
18
- it { should == 'ZXC' }
18
+ it { is_expected.to eq('ZXC') }
19
19
  end
20
20
 
21
21
  describe '#content' do
22
22
  subject { frame.content }
23
- it { should == 'foobar' }
23
+ it { is_expected.to eq('foobar') }
24
24
  end
25
25
 
26
26
  describe '#inspect' do
27
27
  it 'should be pretty inspectable' do
28
- frame.inspect.should eq('<ID3Tag::Frames::V2::UniqueFileIdFrame UFID: ZXC>')
28
+ expect(frame.inspect).to eq('<ID3Tag::Frames::V2::UniqueFileIdFrame UFID: ZXC>')
29
29
  end
30
30
  end
31
31
  end
@@ -12,8 +12,23 @@ describe ID3Tag::Frames::V2::UserTextFrame do
12
12
  let(:text) { "SUPER_FRAME\x00Glāzšķūņrūķīši" }
13
13
  subject { described_class.new(id, raw_content, flags, major_version_number) }
14
14
 
15
- its(:id) { should == :TXX }
16
- its(:content) { should == 'Glāzšķūņrūķīši' }
17
- its(:description) { should == 'SUPER_FRAME' }
18
- its(:inspect) { should eq('<ID3Tag::Frames::V2::UserTextFrame TXX: Glāzšķūņrūķīši>') }
15
+ describe '#id' do
16
+ subject { super().id }
17
+ it { is_expected.to eq(:TXX) }
18
+ end
19
+
20
+ describe '#content' do
21
+ subject { super().content }
22
+ it { is_expected.to eq('Glāzšķūņrūķīši') }
23
+ end
24
+
25
+ describe '#description' do
26
+ subject { super().description }
27
+ it { is_expected.to eq('SUPER_FRAME') }
28
+ end
29
+
30
+ describe '#inspect' do
31
+ subject { super().inspect }
32
+ it { is_expected.to eq('<ID3Tag::Frames::V2::UserTextFrame TXX: Glāzšķūņrūķīši>') }
33
+ end
19
34
  end
@@ -11,22 +11,22 @@ describe ID3Tag::ID3V1FrameParser do
11
11
 
12
12
  it "should contain title frame" do
13
13
  frame = subject.select { |frame| frame.id == :title }.first
14
- frame.content.should == "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaA"
14
+ expect(frame.content).to eq("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaA")
15
15
  end
16
16
 
17
17
  it "should contain artist frame" do
18
18
  frame = subject.select { |frame| frame.id == :artist }.first
19
- frame.content.should == "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbB"
19
+ expect(frame.content).to eq("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbB")
20
20
  end
21
21
 
22
22
  it "should contain album frame" do
23
23
  frame = subject.select { |frame| frame.id == :album }.first
24
- frame.content.should == "cccccccccccccccccccccccccccccC"
24
+ expect(frame.content).to eq("cccccccccccccccccccccccccccccC")
25
25
  end
26
26
 
27
27
  it "should contain year frame" do
28
28
  frame = subject.select { |frame| frame.id == :year }.first
29
- frame.content.should == "2003"
29
+ expect(frame.content).to eq("2003")
30
30
  end
31
31
  end
32
32
 
@@ -34,28 +34,28 @@ describe ID3Tag::ID3V1FrameParser do
34
34
  context "when reading v1.0 tag" do
35
35
  it "should contain comments frame" do
36
36
  frame = subject.select { |frame| frame.id == :comments }.first
37
- frame.content.should == "dddddddddddddddddddddddddddddD"
37
+ expect(frame.content).to eq("dddddddddddddddddddddddddddddD")
38
38
  end
39
39
 
40
40
  it "should contain genre frame" do
41
41
  frame = subject.select { |frame| frame.id == :genre }.first
42
- frame.content.should == "Blues"
42
+ expect(frame.content).to eq("Blues")
43
43
  end
44
44
 
45
45
  it "should not contain track nr frame" do
46
- subject.select { |frame| frame.id == :track_nr }.first.should be_nil
46
+ expect(subject.select { |frame| frame.id == :track_nr }.first).to be_nil
47
47
  end
48
48
  end
49
49
  context "when reading v1.1 tag" do
50
50
  subject { described_class.new(frame_bytes_v1_1).frames }
51
51
  it "should contain comments frame" do
52
52
  frame = subject.select { |frame| frame.id == :comments }.first
53
- frame.content.should == "dddddddddddddddddddddddddddD"
53
+ expect(frame.content).to eq("dddddddddddddddddddddddddddD")
54
54
  end
55
55
 
56
56
  it "should contain track nr frame" do
57
57
  frame = subject.select { |frame| frame.id == :track_nr }.first
58
- frame.content.should == "1"
58
+ expect(frame.content).to eq("1")
59
59
  end
60
60
  end
61
61
  end
@@ -65,7 +65,7 @@ describe ID3Tag::ID3V1FrameParser do
65
65
  let(:tag_body) { File.read mp3_fixture("pov_20131018-2100a.mp3.v1_tag_body") }
66
66
  subject { described_class.new(tag_body) }
67
67
  it "have title" do
68
- subject.frames.find { |f| f.id == :title }.content.should eq("pov_20131018-2100a.mp3")
68
+ expect(subject.frames.find { |f| f.id == :title }.content).to eq("pov_20131018-2100a.mp3")
69
69
  end
70
70
  end
71
71
  end
@@ -6,8 +6,8 @@ describe ID3Tag::ID3V2FrameParser do
6
6
  let(:tag_major_version) { 2 }
7
7
  let(:frame_bytes) { "TP2\u0000\u0000\u0004\u0000ABC" + "TP1\u0000\u0000\u0004\u0000DEF" }
8
8
  it "should fabricate frames" do
9
- ID3Tag::Frames::V2::FrameFabricator.should_receive(:fabricate).with('TP2', "\u0000ABC", nil, 2).once
10
- ID3Tag::Frames::V2::FrameFabricator.should_receive(:fabricate).with('TP1', "\u0000DEF", nil, 2).once
9
+ expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TP2', "\u0000ABC", nil, 2).once
10
+ expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TP1', "\u0000DEF", nil, 2).once
11
11
  subject.frames
12
12
  end
13
13
  end
@@ -15,8 +15,8 @@ describe ID3Tag::ID3V2FrameParser do
15
15
  let(:tag_major_version) { 3 }
16
16
  let(:frame_bytes) { "TIT2\u0000\u0000\u0000\u0004\u0000\u0000\u0000ABC" + "TIT1\u0000\u0000\u0000\u0004\u0000\u0000\u0000DEF" }
17
17
  it "should fabricate frames" do
18
- ID3Tag::Frames::V2::FrameFabricator.should_receive(:fabricate).with('TIT2', "\u0000ABC", "\u0000\u0000", 3).once
19
- ID3Tag::Frames::V2::FrameFabricator.should_receive(:fabricate).with('TIT1', "\u0000DEF", "\u0000\u0000", 3).once
18
+ expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT2', "\u0000ABC", "\u0000\u0000", 3).once
19
+ expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT1', "\u0000DEF", "\u0000\u0000", 3).once
20
20
  subject.frames
21
21
  end
22
22
  end
@@ -24,8 +24,8 @@ describe ID3Tag::ID3V2FrameParser do
24
24
  let(:tag_major_version) { 4 }
25
25
  let(:frame_bytes) { "TIT2\u0000\u0000\u0000\u0004\u0000\u0000\u0000ABC" + "TIT1\u0000\u0000\u0000\u0004\u0000\u0000\u0000DEF" }
26
26
  it "should fabricate frames" do
27
- ID3Tag::Frames::V2::FrameFabricator.should_receive(:fabricate).with('TIT2', "\u0000ABC", "\u0000\u0000", 4).once
28
- ID3Tag::Frames::V2::FrameFabricator.should_receive(:fabricate).with('TIT1', "\u0000DEF", "\u0000\u0000", 4).once
27
+ expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT2', "\u0000ABC", "\u0000\u0000", 4).once
28
+ expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT1', "\u0000DEF", "\u0000\u0000", 4).once
29
29
  subject.frames
30
30
  end
31
31
  end