satori_like_dictionary 0.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2ff264a3d70e5ea90f99df8d6bc127ef8779fdc8
4
+ data.tar.gz: 95c82a2e4f2942612202ba5dd856e2e1e3c48ebc
5
+ SHA512:
6
+ metadata.gz: c61473990fce6eaa16a07e89a9743fb87fbc37503a6b81d507077a9959c626e7a3d81b266125c481499b4c1ea8c4f89435d9d02f056ad7347f2b20c93ad1a024
7
+ data.tar.gz: 0160015705a0962e3509a4fe57631b2d470dcb5810eff5522520e55fb158d65bb353241d202126db6091b0aa2ea93fad4929efa0dacae1405bd435dc4cb7dace
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /doc/
6
+ /coverage/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .*.sw?
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format doc
3
+ --require ./spec/spec_helper.rb
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ os:
5
+ - linux
6
+ - osx
7
+ script: bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in shioruby.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # [SatoriLikeDictionary](https://github.com/Narazaka/satori_like_dictionary)
2
+
3
+ [![Gem](https://img.shields.io/gem/v/satori_like_dictionary.svg)](https://rubygems.org/gems/satori_like_dictionary)
4
+ [![Gem](https://img.shields.io/gem/dtv/satori_like_dictionary.svg)](https://rubygems.org/gems/satori_like_dictionary)
5
+ [![Gemnasium](https://gemnasium.com/Narazaka/satori_like_dictionary.svg)](https://gemnasium.com/Narazaka/satori_like_dictionary)
6
+ [![Inch CI](http://inch-ci.org/github/Narazaka/satori_like_dictionary.svg)](http://inch-ci.org/github/Narazaka/satori_like_dictionary)
7
+ [![Travis Build Status](https://travis-ci.org/Narazaka/satori_like_dictionary.svg)](https://travis-ci.org/Narazaka/satori_like_dictionary)
8
+ [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/Narazaka/satori_like_dictionary?svg=true)](https://ci.appveyor.com/project/Narazaka/satori-like-dictionary)
9
+ [![codecov.io](https://codecov.io/github/Narazaka/satori_like_dictionary/coverage.svg?branch=master)](https://codecov.io/github/Narazaka/satori_like_dictionary?branch=master)
10
+ [![Code Climate](https://codeclimate.com/github/Narazaka/satori_like_dictionary/badges/gpa.svg)](https://codeclimate.com/github/Narazaka/satori_like_dictionary)
11
+
12
+ Satori like dictionary for Ukagaka SHIORI subsystems
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'satori_like_dictionary'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install satori_like_dictionary
29
+
30
+ ## Satori Like Dictionary
31
+
32
+ ```
33
+ ファイル先頭から最初の*あるいは@までコメント
34
+
35
+ *OnAITalk
36
+ :さくらがわ
37
+ :けろがわ
38
+ #コメント
39
+ #コメント行の改行は維持されない(里々と異なる
40
+ :わー
41
+
42
+
43
+ :ランダムトーク
44
+
45
+ @単語
46
+ 単語1
47
+ 単語2
48
+ >などの行頭記号は効果がない
49
+
50
+
51
+ >指定されたエントリ名へ飛ぶ
52
+ #>のあとのものは表示されない
53
+ ここは表示されない
54
+
55
+
56
+ →さくら
57
+ #話しかける相手を指定(里々と異なる
58
+ さくらさん!
59
+
60
+
61
+ $variable = "aaa"
62
+ #$はrubyコードを書く(里々と異なる
63
+
64
+
65
+ _選択肢1
66
+ _選択肢2 _選択肢3
67
+ #選択肢は1行ではなく空白までとなった(里々と異なる
68
+
69
+
70
+ (1)(2)(42)
71
+ #(数字)は\s[数字]に変換
72
+
73
+
74
+ (単語)
75
+ #(文字列)は該当するエントリがある場合それを表示
76
+
77
+
78
+ <%= 1 + 1 %>
79
+ #コードはerb風の表記で記述(里々での「(関数or変数等)」の用法の括弧は消滅
80
+
81
+
82
+ #erb風の諸々
83
+ % num = 42
84
+ %= num
85
+ <% num *= 2 %>
86
+ <%= num %>
87
+
88
+
89
+ :主に利用できる値
90
+ %= events.to_s # イベント定義オブジェクト
91
+ %= request.Reference0 # リクエストオブジェクト
92
+ %= r0 # request.Reference0の短縮表記
93
+
94
+
95
+ :句読点に待ち時間をつけるなど、単純な置換で再現できるものはこのライブラリでは行わない。
96
+
97
+ ```
98
+
99
+ ## API
100
+
101
+ [API Document](http://www.rubydoc.info/github/Narazaka/satori_like_dictionary)
102
+
103
+ ## License
104
+
105
+ This is released under [MIT License](http://narazaka.net/license/MIT?2016).
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'yard'
4
+ require 'yard/rake/yardoc_task'
5
+
6
+ task :default => :spec
7
+
8
+ RSpec::Core::RakeTask.new
9
+ YARD::Rake::YardocTask.new
data/appveyor.yml ADDED
@@ -0,0 +1,20 @@
1
+ version: "{build}"
2
+ branches:
3
+ except:
4
+ - gh-pages
5
+ install:
6
+ - set RUBY_HOME=C:\Ruby%ruby_version%
7
+ - set PATH=%RUBY_HOME%\bin;%PATH%
8
+ - ruby --version
9
+ - gem --version
10
+ - gem install bundler --no-document
11
+ - bundle --version
12
+ - bundle install
13
+ test_script:
14
+ - bundle exec rake spec
15
+ build: off
16
+ deploy: off
17
+ environment:
18
+ matrix:
19
+ - ruby_version: 22
20
+ - ruby_version: 22-x64
@@ -0,0 +1,333 @@
1
+ require 'nano_template'
2
+ require 'ostruct'
3
+
4
+ # Satori like dictionary for Ukagaka SHIORI subsystem
5
+ class SatoriLikeDictionary
6
+ attr_reader :dictionary
7
+
8
+ # initialize SatoriLikeDictionary
9
+ # @param [Events] events events definition (if nil then use the dictionary itself)
10
+ def initialize(events=nil)
11
+ @dictionary = OpenStruct.new
12
+ @events = events || @dictionary
13
+ end
14
+
15
+ # load all files in a directory as satori like dictionaries
16
+ # @param [String] directory path to dictionary
17
+ # @param [String] ext file extension filter
18
+ def load_all(directory, ext = 'txt')
19
+ files = Dir[File.join(directory, "*.#{ext}")]
20
+ files.each {|file| parse(File.read(file))}
21
+ end
22
+
23
+ # load a file as satori like dictionary
24
+ # @param [String] file path to file
25
+ def load(file)
26
+ parse(File.read(file))
27
+ end
28
+
29
+ # parse and register satori like dictionary source
30
+ # @param [String] source satori like dictionary source
31
+ def parse(source)
32
+ scope = :comment
33
+ current_entry = nil
34
+ entry_name = nil
35
+ source.each_line do |line|
36
+ line = line.chomp
37
+ if line.start_with?("#")
38
+ # skip comment line (incompatible with satori original)
39
+ elsif line.start_with?("*")
40
+ scope = :entry
41
+ entry_name = linebody(line).strip
42
+ current_entry = Entry.new
43
+ @dictionary[entry_name] ||= Entries.new
44
+ @dictionary[entry_name] << current_entry
45
+ elsif line.start_with?("@")
46
+ scope = :word_entry
47
+ entry_name = linebody(line).strip
48
+ else
49
+ if scope == :entry
50
+ if line.start_with?("$") # incompatible with satori original ($ruby code (same as %)
51
+ current_entry << Code.new(linebody(line))
52
+ elsif line.start_with?(":")
53
+ current_entry << ChangeScopeLine.new(linebody(line))
54
+ elsif line.start_with?(">")
55
+ current_entry << Jump.new(linebody(line))
56
+ elsif line.start_with?("→") # incompatible with satori original (→キャラ名
57
+ current_entry << Call.new(linebody(line))
58
+ elsif line.start_with?("≫")
59
+ $stderr.puts "警告: ≫は実装されていません。スキップします。"
60
+ else
61
+ current_entry << Line.new(line)
62
+ end
63
+ elsif scope == :word_entry
64
+ if line.start_with?("$", ">", "≫", "→")
65
+ $stderr.puts "警告: @の中で行頭#{line[0]}が使われています。文字列として解釈されます。"
66
+ end
67
+ unless line.strip.empty? # skip empty line
68
+ @dictionary[entry_name] ||= Entries.new
69
+ @dictionary[entry_name] << Word.new(line)
70
+ end
71
+ end
72
+ # skip :comment scope
73
+ end
74
+ end
75
+ end
76
+
77
+ # call a named entry
78
+ # @param [String] entry_name entry name
79
+ # @param [OpenStruct] request request hash
80
+ # @return [String|OpenStruct] result
81
+ def talk(entry_name, request)
82
+ if entries = @dictionary[entry_name]
83
+ entries.render(@events, request)
84
+ else
85
+ nil
86
+ end
87
+ end
88
+
89
+ # call the "ai talk" entry
90
+ # @param [OpenStruct] request request hash
91
+ # @return [String|OpenStruct] result
92
+ def aitalk(request)
93
+ talk("", request)
94
+ end
95
+
96
+ # satori token renderer
97
+ module Renderer
98
+ # number map
99
+ NUMBERS = {"0" => 0, "1" => 1, "2" => 2, "3" => 3, "4" => 4, "5" => 5, "6" => 6, "7" => 7, "8" => 8, "9" => 9}
100
+
101
+ # execute template
102
+ # @param [Events] events events definition
103
+ # @param [OpenStruct] request request hash
104
+ # @return [String] result
105
+ def render_template(events, request)
106
+ template = NanoTemplate.new.template(to_template)
107
+ context = TemplateContext.new(events, request)
108
+ template.call(context)
109
+ end
110
+
111
+ # process basic replacements
112
+ # @param [Events] events events definition
113
+ # @param [OpenStruct] request request hash
114
+ # @return [String] result
115
+ def render_base(events, request)
116
+ value = render_template(events, request)
117
+ .gsub(/_(\S+)/, "\\q[\\1]")
118
+ .gsub(/(([^)]*))/) do
119
+ content = $1
120
+ if content.match(/^[0-90-9]+$/)
121
+ "\\s[#{content.gsub(/[0-9]/) {|m| NUMBERS[m]} }]"
122
+ else
123
+ begin
124
+ entry = events.send(content, request) # event
125
+ rescue ArgumentError
126
+ entry = events.send(content) # satori dictionary
127
+ rescue NoMethodError
128
+ entry = nil # wrong event
129
+ end
130
+ if entry.respond_to?(:render) # satori entry
131
+ entry.render(events, request)
132
+ elsif entry.respond_to?(:Value) # ostruct value
133
+ entry.Value
134
+ else # simple value
135
+ entry
136
+ end
137
+ end
138
+ end
139
+ .gsub(/\r?\n/, "\\n")
140
+ value
141
+ end
142
+
143
+ # render the content
144
+ # @param [Events] events events definition
145
+ # @param [OpenStruct] request request hash
146
+ # @return [String|OpenStruct] result
147
+ def render(events, request)
148
+ value = render_base(events, request)
149
+ if request.__satori_target_character
150
+ OpenStruct.new({Value: value, Reference0: request.__satori_target_character})
151
+ else
152
+ value
153
+ end
154
+ end
155
+ end
156
+
157
+ # line (normal line in entries)
158
+ class Line < String
159
+ # to template
160
+ # @return [String] template
161
+ def to_template
162
+ self + "\n"
163
+ end
164
+ end
165
+
166
+ # line with change scope (:)
167
+ class ChangeScopeLine < String
168
+ # to template
169
+ # @return [String] template
170
+ def to_template
171
+ "<%= change_scope %>" + self + "\n"
172
+ end
173
+ end
174
+
175
+ # code ($)
176
+ class Code < String
177
+ # to template
178
+ # @return [String] template
179
+ def to_template
180
+ "<% #{self} %>"
181
+ end
182
+ end
183
+
184
+ # jump (>)
185
+ class Jump < String
186
+ # to template
187
+ # @return [String] template
188
+ def to_template
189
+ "<%= jump_to('#{self.gsub(/'/) {"\\'"}}') %>"
190
+ end
191
+ end
192
+
193
+ # communication call (→)
194
+ class Call < String
195
+ # to template
196
+ # @return [String] template
197
+ def to_template
198
+ "<% call_to('#{self.gsub(/'/) {"\\'"}}') %>"
199
+ end
200
+ end
201
+
202
+ # word (@)
203
+ class Word < String
204
+ include Renderer
205
+ alias_method :to_template, :to_s
206
+ end
207
+
208
+ # entry (*)
209
+ class Entry < Array
210
+ include Renderer
211
+
212
+ # @param [Events] events events definition
213
+ # @param [OpenStruct] request request hash
214
+ def render_base(events, request)
215
+ '\1' + super
216
+ end
217
+
218
+ # to template
219
+ # @return [String] template
220
+ def to_template
221
+ still_empty = true
222
+ reverse.reject do |element| # remove last empty lines
223
+ still_empty = still_empty && element.is_a?(Line) && element.empty?
224
+ end.map do |element|
225
+ element.to_template
226
+ end.reverse.join('').chomp
227
+ end
228
+ end
229
+
230
+ # random select entries
231
+ class Entries < Array
232
+ # render the content
233
+ # @param [Events] events events definition
234
+ # @param [OpenStruct] request request hash
235
+ def render(events, request)
236
+ shuffle.first.render(events, request)
237
+ end
238
+ end
239
+
240
+ # template runtime context class
241
+ class TemplateContext < OpenStruct
242
+ attr_reader :events, :request
243
+
244
+ # initialize context
245
+ # @param [Events] events events definition
246
+ # @param [OpenStruct] request request hash
247
+ def initialize(events, request)
248
+ @events = events
249
+ @request = request
250
+ end
251
+
252
+ # change character scope
253
+ def change_scope
254
+ request.__satori_scope = request.__satori_scope.nil? || request.__satori_scope == 1 ? 0 : 1
255
+ '\\' + request.__satori_scope.to_s
256
+ end
257
+
258
+ # jump to entry
259
+ def jump_to(target_entry)
260
+ "(#{target_entry})\\e"
261
+ end
262
+
263
+ # set communication target
264
+ def call_to(target_character)
265
+ request.__satori_target_character = target_character
266
+ end
267
+
268
+ # method_missing
269
+ def method_missing(method_name, *args)
270
+ if result = method_name.match(/^r(\d+)$/) # r0 -> request.Reference0
271
+ request["Reference#{result[1]}"]
272
+ else
273
+ super
274
+ end
275
+ end
276
+ end
277
+
278
+ private
279
+
280
+ def linebody(line)
281
+ line[1...line.size]
282
+ end
283
+ end
284
+
285
+ # satori like template integrated events base class
286
+ class SatoriLikeDictionaryIntegratedEvents
287
+
288
+ # initialize events
289
+ def initialize
290
+ @satori_like_dictionary = SatoriLikeDictionary.new(self)
291
+ end
292
+
293
+ private
294
+
295
+ # load all files in a directory as satori like dictionaries
296
+ # @param [String] file path to file
297
+ def load_file(file)
298
+ @satori_like_dictionary.load(file)
299
+ end
300
+
301
+ # load a file as satori like dictionary
302
+ # @param [String] directory path to dictionary
303
+ # @param [String] ext file extension filter
304
+ def load_all_dictionary(directory, ext = 'txt')
305
+ @satori_like_dictionary.load_all(directory, ext)
306
+ end
307
+
308
+ # call a named entry
309
+ # @param [OpenStruct] request request hash
310
+ # @param [String] method from method name
311
+ # @return [String|OpenStruct] result
312
+ def talk(request, method = nil)
313
+ unless method
314
+ # detect caller method name (= request ID)
315
+ if RUBY_ENGINE == 'opal'
316
+ matched = caller[1].match(/\[as \$(.*?)\]/)
317
+ return unless matched
318
+ method = matched[1]
319
+ else
320
+ method = caller_locations.first.label
321
+ end
322
+ end
323
+ @satori_like_dictionary.talk(method, request)
324
+ end
325
+
326
+ # call a "ai talk" entry
327
+ # @param [OpenStruct] request request hash
328
+ # @return [String|OpenStruct] result
329
+ def aitalk(request)
330
+ @satori_like_dictionary.aitalk(request)
331
+ end
332
+
333
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+
4
+ Gem::Specification.new do |spec|
5
+ spec.name = "satori_like_dictionary"
6
+ spec.version = "0.0.1"
7
+ spec.authors = ["Narazaka"]
8
+ spec.email = ["info@narazaka.net"]
9
+
10
+ spec.summary = %q{Satori like dictionary for Ukagaka SHIORI subsystems}
11
+ spec.description = %q{Satori like dictionary for Ukagaka SHIORI subsystems}
12
+ spec.homepage = "https://github.com/Narazaka/satori_like_dictionary"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.require_paths = ["lib"]
17
+
18
+ spec.add_development_dependency "bundler", ">= 1.7.9"
19
+ spec.add_development_dependency "rake", "~> 10.0"
20
+ spec.add_development_dependency "rspec", "~> 3.4"
21
+ spec.add_development_dependency "yard", "~> 0.8.7"
22
+ spec.add_development_dependency "simplecov", "~> 0.11"
23
+ spec.add_development_dependency "codecov", "~> 0.1"
24
+ spec.add_dependency "nano_template", ">= 0.0.3"
25
+ end
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: satori_like_dictionary
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Narazaka
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.7.9
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.7.9
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.4'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.7
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.7
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.11'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.11'
83
+ - !ruby/object:Gem::Dependency
84
+ name: codecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.1'
97
+ - !ruby/object:Gem::Dependency
98
+ name: nano_template
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 0.0.3
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.0.3
111
+ description: Satori like dictionary for Ukagaka SHIORI subsystems
112
+ email:
113
+ - info@narazaka.net
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - ".travis.yml"
121
+ - Gemfile
122
+ - README.md
123
+ - Rakefile
124
+ - appveyor.yml
125
+ - lib/satori_like_dictionary.rb
126
+ - satori_like_dictionary.gemspec
127
+ homepage: https://github.com/Narazaka/satori_like_dictionary
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.4.5.1
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Satori like dictionary for Ukagaka SHIORI subsystems
151
+ test_files: []
152
+ has_rdoc: