ikku 0.0.9 → 0.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +15 -9
- data/lib/ikku/bracket_state.rb +52 -0
- data/lib/ikku/node.rb +1 -1
- data/lib/ikku/reviewer.rb +10 -10
- data/lib/ikku/scanner.rb +14 -16
- data/lib/ikku/song.rb +61 -0
- data/lib/ikku/version.rb +1 -1
- data/spec/ikku/reviewer_spec.rb +47 -15
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3096ad7728dd91f17e2176eed31a6a5cf7b9666
|
4
|
+
data.tar.gz: a9a26afdf48c5a96da3e4e963442aefe19744916
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b455889d0947433f9124f57ec84d4198e284d2e9e273a24b33aa3039e879bc8c811073beacb6951a865f58e8e1444ea83489c83fdf0015b662922731e9f5cfd
|
7
|
+
data.tar.gz: 91ecfbb73a4a8cd7186443d3f4adebdb933ddcab0cbc06e7a2239144092727469400eb14e450fd01de6708f028a76497d748715cd14f743fbeeae9a35d02656e
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -15,7 +15,7 @@ reviewer = Ikku::Reviewer.new
|
|
15
15
|
```
|
16
16
|
|
17
17
|
### Ikku::Reviewer#judge
|
18
|
-
Judge if given text is
|
18
|
+
Judge if given text is valid song or not.
|
19
19
|
|
20
20
|
```rb
|
21
21
|
reviewer.judge("古池や蛙飛び込む水の音") #=> true
|
@@ -23,27 +23,33 @@ reviewer.judge("ああ古池や蛙飛び込む水の音ああ") #=> false
|
|
23
23
|
```
|
24
24
|
|
25
25
|
### Ikku::Reviewer#find
|
26
|
-
Find one
|
26
|
+
Find one valid song from given text.
|
27
27
|
|
28
28
|
```rb
|
29
29
|
reviewer.find("ああ古池や蛙飛び込む水の音ああ")
|
30
|
-
#=>
|
30
|
+
#=> #<Ikku::Song>
|
31
31
|
```
|
32
32
|
|
33
33
|
### Ikku::Reviewer#search
|
34
|
-
Search all
|
34
|
+
Search all valid songs from given text.
|
35
35
|
|
36
36
|
```rb
|
37
37
|
reviewer.search("ああ古池や蛙飛び込む水の音ああ天秤や京江戸かけて千代の春ああ")
|
38
38
|
#=> [
|
39
|
-
#
|
40
|
-
#
|
39
|
+
# #<Ikku::Song>,
|
40
|
+
# #<Ikku::Song>,
|
41
41
|
# ]
|
42
|
-
#
|
43
42
|
```
|
44
43
|
|
45
|
-
###
|
46
|
-
|
44
|
+
### Ikku::Song#phrases
|
45
|
+
Returns an Array of phrases of `Ikku::Node`.
|
46
|
+
|
47
|
+
```rb
|
48
|
+
song.phrases #=> [["古池", "や"], ["蛙", "飛び込む"], ["水", "の", "音"]]
|
49
|
+
```
|
50
|
+
|
51
|
+
### Rule option
|
52
|
+
Pass `:rule` option to change the measure rule (default: `[5, 7, 5]`).
|
47
53
|
|
48
54
|
```rb
|
49
55
|
reviewer = Ikku::Reviewer.new(rule: [4, 3, 5])
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Ikku
|
2
|
+
class BracketState
|
3
|
+
TABLE = {
|
4
|
+
"’" => "‘",
|
5
|
+
"”" => "“",
|
6
|
+
")" => "(",
|
7
|
+
")" => "(",
|
8
|
+
"]" => "[",
|
9
|
+
"]" => "[",
|
10
|
+
"}" => "{",
|
11
|
+
"}" => "{",
|
12
|
+
"〉" => "〈",
|
13
|
+
"》" => "《",
|
14
|
+
"」" => "「",
|
15
|
+
"』" => "『",
|
16
|
+
"】" => "【",
|
17
|
+
"〕" => "〔",
|
18
|
+
">" => "<",
|
19
|
+
">" => "<",
|
20
|
+
}
|
21
|
+
|
22
|
+
def consume_all(surfaces)
|
23
|
+
surfaces.each do |surface|
|
24
|
+
consume(surface)
|
25
|
+
end
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def odd?
|
30
|
+
!even?
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def consume(surface)
|
36
|
+
case
|
37
|
+
when TABLE.values.include?(surface)
|
38
|
+
stack.push(surface)
|
39
|
+
when TABLE.include?(surface) && stack.last == TABLE[surface]
|
40
|
+
stack.pop
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def even?
|
45
|
+
stack.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def stack
|
49
|
+
@stack ||= []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/ikku/node.rb
CHANGED
data/lib/ikku/reviewer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require "ikku/parser"
|
2
|
-
require "ikku/
|
2
|
+
require "ikku/song"
|
3
3
|
|
4
4
|
module Ikku
|
5
5
|
class Reviewer
|
@@ -7,30 +7,30 @@ module Ikku
|
|
7
7
|
@rule = rule
|
8
8
|
end
|
9
9
|
|
10
|
-
# Find one
|
11
|
-
# @return [
|
10
|
+
# Find one valid song from given text.
|
11
|
+
# @return [Ikku::Song]
|
12
12
|
def find(text)
|
13
13
|
nodes = parser.parse(text)
|
14
14
|
nodes.length.times.find do |index|
|
15
|
-
if (
|
16
|
-
break
|
15
|
+
if (song = Song.new(nodes[index..-1], rule: @rule)).valid?
|
16
|
+
break song
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
# Judge if given text is
|
21
|
+
# Judge if given text is valid song or not.
|
22
22
|
# @return [true, false]
|
23
23
|
def judge(text)
|
24
|
-
|
24
|
+
Song.new(parser.parse(text), exactly: true, rule: @rule).valid?
|
25
25
|
end
|
26
26
|
|
27
|
-
# Search all
|
27
|
+
# Search all valid songs from given text.
|
28
28
|
# @return [Array<Array>]
|
29
29
|
def search(text)
|
30
30
|
nodes = parser.parse(text)
|
31
31
|
nodes.length.times.map do |index|
|
32
|
-
|
33
|
-
end.
|
32
|
+
Song.new(nodes[index..-1], rule: @rule)
|
33
|
+
end.select(&:valid?)
|
34
34
|
end
|
35
35
|
|
36
36
|
private
|
data/lib/ikku/scanner.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
module Ikku
|
2
|
-
# Find one
|
2
|
+
# Find one set of valid phrases that starts from the 1st node of given nodes.
|
3
3
|
class Scanner
|
4
|
-
DEFAULT_RULE = [5, 7, 5]
|
5
|
-
|
6
4
|
attr_writer :count
|
7
5
|
|
8
|
-
def initialize(
|
6
|
+
def initialize(exactly: false, nodes: nil, rule: nil)
|
9
7
|
@exactly = exactly
|
10
8
|
@nodes = nodes
|
11
9
|
@rule = rule
|
@@ -17,17 +15,17 @@ module Ikku
|
|
17
15
|
end
|
18
16
|
|
19
17
|
def scan
|
20
|
-
if has_valid_first_node?
|
18
|
+
if has_valid_first_node?
|
21
19
|
@nodes.each_with_index do |node, index|
|
22
20
|
if consume(node)
|
23
|
-
if
|
21
|
+
if satisfied?
|
24
22
|
return phrases unless @exactly
|
25
23
|
end
|
26
24
|
else
|
27
25
|
return
|
28
26
|
end
|
29
27
|
end
|
30
|
-
phrases if
|
28
|
+
phrases if satisfied?
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
@@ -52,13 +50,13 @@ module Ikku
|
|
52
50
|
end
|
53
51
|
|
54
52
|
def first_of_phrase?
|
55
|
-
rule.inject([]) do |array, length|
|
53
|
+
@rule.inject([]) do |array, length|
|
56
54
|
array << array.last.to_i + length
|
57
55
|
end.include?(count)
|
58
56
|
end
|
59
57
|
|
60
58
|
def has_full_count?
|
61
|
-
count == rule.inject(0, :+)
|
59
|
+
count == @rule.inject(0, :+)
|
62
60
|
end
|
63
61
|
|
64
62
|
def has_valid_first_node?
|
@@ -66,25 +64,25 @@ module Ikku
|
|
66
64
|
end
|
67
65
|
|
68
66
|
def has_valid_last_node?
|
69
|
-
|
67
|
+
phrases.last.last.last_of_ikku?
|
70
68
|
end
|
71
69
|
|
72
70
|
def max_consumable_length
|
73
|
-
rule[0..phrase_index].inject(0, :+) - count
|
71
|
+
@rule[0..phrase_index].inject(0, :+) - count
|
74
72
|
end
|
75
73
|
|
76
74
|
def phrase_index
|
77
|
-
rule.length.times.find do |index|
|
78
|
-
count < rule[0..index].inject(0, :+)
|
79
|
-
end || rule.length - 1
|
75
|
+
@rule.length.times.find do |index|
|
76
|
+
count < @rule[0..index].inject(0, :+)
|
77
|
+
end || @rule.length - 1
|
80
78
|
end
|
81
79
|
|
82
80
|
def phrases
|
83
81
|
@phrases ||= []
|
84
82
|
end
|
85
83
|
|
86
|
-
def
|
87
|
-
|
84
|
+
def satisfied?
|
85
|
+
has_full_count? && has_valid_last_node?
|
88
86
|
end
|
89
87
|
end
|
90
88
|
end
|
data/lib/ikku/song.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require "ikku/bracket_state"
|
2
|
+
require "ikku/scanner"
|
3
|
+
|
4
|
+
module Ikku
|
5
|
+
class Song
|
6
|
+
DEFAULT_RULE = [5, 7, 5]
|
7
|
+
|
8
|
+
def initialize(nodes, exactly: false, rule: nil)
|
9
|
+
@exactly = exactly
|
10
|
+
@nodes = nodes
|
11
|
+
@rule = rule
|
12
|
+
end
|
13
|
+
|
14
|
+
def phrases
|
15
|
+
if instance_variable_defined?(:@phrases)
|
16
|
+
@phrases
|
17
|
+
else
|
18
|
+
@phrases = scan
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid?
|
23
|
+
case
|
24
|
+
when phrases.nil?
|
25
|
+
false
|
26
|
+
when has_odd_parentheses?
|
27
|
+
false
|
28
|
+
else
|
29
|
+
true
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def has_odd_parentheses?
|
36
|
+
bracket_state.odd?
|
37
|
+
end
|
38
|
+
|
39
|
+
def nodes
|
40
|
+
phrases.flatten
|
41
|
+
end
|
42
|
+
|
43
|
+
def rule
|
44
|
+
@rule || DEFAULT_RULE
|
45
|
+
end
|
46
|
+
|
47
|
+
def scan
|
48
|
+
Scanner.new(exactly: @exactly, nodes: @nodes, rule: rule).scan
|
49
|
+
end
|
50
|
+
|
51
|
+
def bracket_state
|
52
|
+
@bracket_state ||= BracketState.new.tap do |state|
|
53
|
+
state.consume_all(surfaces)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def surfaces
|
58
|
+
nodes.map(&:surface)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/ikku/version.rb
CHANGED
data/spec/ikku/reviewer_spec.rb
CHANGED
@@ -18,7 +18,7 @@ RSpec.describe Ikku::Reviewer do
|
|
18
18
|
instance.find(text)
|
19
19
|
end
|
20
20
|
|
21
|
-
context "
|
21
|
+
context "with invalid song" do
|
22
22
|
let(:text) do
|
23
23
|
"test"
|
24
24
|
end
|
@@ -26,16 +26,24 @@ RSpec.describe Ikku::Reviewer do
|
|
26
26
|
it { is_expected.to be_nil }
|
27
27
|
end
|
28
28
|
|
29
|
-
context "with valid
|
30
|
-
it { is_expected.to be_a
|
29
|
+
context "with valid song" do
|
30
|
+
it { is_expected.to be_a Ikku::Song }
|
31
31
|
end
|
32
32
|
|
33
|
-
context "with text including
|
33
|
+
context "with text including song" do
|
34
34
|
let(:text) do
|
35
35
|
"ああ#{super()}ああ"
|
36
36
|
end
|
37
37
|
|
38
|
-
it { is_expected.to be_a
|
38
|
+
it { is_expected.to be_a Ikku::Song }
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with text including song ending with 連用タ接続" do
|
42
|
+
let(:text) do
|
43
|
+
"リビングでコーヒー飲んでだめになってる"
|
44
|
+
end
|
45
|
+
|
46
|
+
it { is_expected.to be_nil }
|
39
47
|
end
|
40
48
|
end
|
41
49
|
|
@@ -44,11 +52,11 @@ RSpec.describe Ikku::Reviewer do
|
|
44
52
|
instance.judge(text)
|
45
53
|
end
|
46
54
|
|
47
|
-
context "with valid
|
55
|
+
context "with valid song" do
|
48
56
|
it { is_expected.to be true }
|
49
57
|
end
|
50
58
|
|
51
|
-
context "with invalid
|
59
|
+
context "with invalid song" do
|
52
60
|
let(:text) do
|
53
61
|
"#{super()}ああ"
|
54
62
|
end
|
@@ -56,7 +64,7 @@ RSpec.describe Ikku::Reviewer do
|
|
56
64
|
it { is_expected.to be false }
|
57
65
|
end
|
58
66
|
|
59
|
-
context "with rule option and valid
|
67
|
+
context "with rule option and valid song" do
|
60
68
|
let(:rule) do
|
61
69
|
[4, 3, 5]
|
62
70
|
end
|
@@ -68,7 +76,7 @@ RSpec.describe Ikku::Reviewer do
|
|
68
76
|
it { is_expected.to be true }
|
69
77
|
end
|
70
78
|
|
71
|
-
context "with rule option and invalid
|
79
|
+
context "with rule option and invalid song" do
|
72
80
|
let(:rule) do
|
73
81
|
[4, 3, 5]
|
74
82
|
end
|
@@ -100,21 +108,45 @@ RSpec.describe Ikku::Reviewer do
|
|
100
108
|
it { is_expected.to be false }
|
101
109
|
end
|
102
110
|
|
103
|
-
context "with
|
111
|
+
context "with song starting with symbol" do
|
104
112
|
let(:text) do
|
105
|
-
"
|
113
|
+
"、#{super()}"
|
106
114
|
end
|
107
115
|
|
108
116
|
it { is_expected.to be false }
|
109
117
|
end
|
110
118
|
|
111
|
-
context "with
|
119
|
+
context "with song ending with 連用タ接続 (撮っ)" do
|
112
120
|
let(:text) do
|
113
121
|
"新宿の桜と庭の写真撮っ"
|
114
122
|
end
|
115
123
|
|
116
124
|
it { is_expected.to be false }
|
117
125
|
end
|
126
|
+
|
127
|
+
context "with song including even parentheses" do
|
128
|
+
let(:text) do
|
129
|
+
"古池や「蛙<飛び込む>」水の音"
|
130
|
+
end
|
131
|
+
|
132
|
+
it { is_expected.to be true }
|
133
|
+
end
|
134
|
+
|
135
|
+
context "with song including odd parentheses" do
|
136
|
+
let(:text) do
|
137
|
+
"古池や「蛙<飛び込む」>水の音"
|
138
|
+
end
|
139
|
+
|
140
|
+
it { is_expected.to be false }
|
141
|
+
end
|
142
|
+
|
143
|
+
context "with song starting with parenthesis" do
|
144
|
+
let(:text) do
|
145
|
+
"(#{super()})"
|
146
|
+
end
|
147
|
+
|
148
|
+
it { is_expected.to be true }
|
149
|
+
end
|
118
150
|
end
|
119
151
|
|
120
152
|
describe "#search" do
|
@@ -122,7 +154,7 @@ RSpec.describe Ikku::Reviewer do
|
|
122
154
|
instance.search(text)
|
123
155
|
end
|
124
156
|
|
125
|
-
context "without
|
157
|
+
context "without song" do
|
126
158
|
let(:text) do
|
127
159
|
"test"
|
128
160
|
end
|
@@ -130,11 +162,11 @@ RSpec.describe Ikku::Reviewer do
|
|
130
162
|
it { is_expected.to be_a Array }
|
131
163
|
end
|
132
164
|
|
133
|
-
context "with valid
|
165
|
+
context "with valid song" do
|
134
166
|
it { is_expected.to be_a Array }
|
135
167
|
end
|
136
168
|
|
137
|
-
context "with text including
|
169
|
+
context "with text including song" do
|
138
170
|
let(:text) do
|
139
171
|
"ああ#{super()}ああ"
|
140
172
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ikku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
@@ -96,10 +96,12 @@ files:
|
|
96
96
|
- Rakefile
|
97
97
|
- ikku.gemspec
|
98
98
|
- lib/ikku.rb
|
99
|
+
- lib/ikku/bracket_state.rb
|
99
100
|
- lib/ikku/node.rb
|
100
101
|
- lib/ikku/parser.rb
|
101
102
|
- lib/ikku/reviewer.rb
|
102
103
|
- lib/ikku/scanner.rb
|
104
|
+
- lib/ikku/song.rb
|
103
105
|
- lib/ikku/version.rb
|
104
106
|
- spec/ikku/reviewer_spec.rb
|
105
107
|
- spec/spec_helper.rb
|