satori_like_dictionary 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: