plasper 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.asc +11 -0
- data.tar.gz.asc +11 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +20 -0
- data/README.md +86 -0
- data/bin/plasper +6 -0
- data/lib/Plasper/options.rb +78 -0
- data/lib/Plasper/plasper.rb +198 -0
- data/lib/Plasper/runner.rb +87 -0
- data/lib/Plasper/version.rb +4 -0
- data/lib/plasper.rb +5 -66
- data/plasper.gemspec +21 -0
- metadata +62 -8
- metadata.gz.asc +11 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b17ea1b2165f60828851b7cde28a39772d34d8eb
|
4
|
+
data.tar.gz: 68bb0895c791c566e260f8b364db6ce6b4316057
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7cd8c0f22f914931d7e68aa86be4513c55a13fc5446ecc4911bb39abc92f8355258e6021d9dde35168dc9de2b55c6a9ffffbbcfe73fddaca72d59b0c6b715091
|
7
|
+
data.tar.gz: 4ca30e761e3688719975597bfe5bf3af8cbbcc319ffe3168dc109b06fa2859f397f8db1865943802d928ddd7a9c69c22d6be2666985e15abf38f52c30560f177
|
checksums.yaml.gz.asc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
-----BEGIN PGP SIGNATURE-----
|
2
|
+
Version: GnuPG v1
|
3
|
+
|
4
|
+
iQEcBAABAgAGBQJWN9A5AAoJEGf2hZJktszzlFAH/3rRQC4BG+ErfJmHNBAlfWcf
|
5
|
+
5XK2fZ9Wm3IC7UO62syfZZ2V2zpVbHuWYzis2E3R6s6rzbPUVx2TElNCDbtDkz3m
|
6
|
+
Ye8q2rVB82OUbtlNwTDwJ1qdRhsuB/iRQrH8S76aQtUyXNG8uIU/qFg6yhO4GGgG
|
7
|
+
0ymDHhRkJqSZXa0MmWBiBa/ILEb5DNcjrlC5PTsu08Lvq+HWP/bKYvXCD7oOUNGj
|
8
|
+
Xmq2WOBWuBnExVLQ/XXW0R2Wh/hT0rlFdDeu+F8JSwz7YxDupJpiZQmJ9Aetv0T/
|
9
|
+
C4wGsaSWYDvr7jI/am1dt9N36EmcyF+9ak1vbfyoaj1y0kIku5I8b9hFc2ea/v0=
|
10
|
+
=T2b4
|
11
|
+
-----END PGP SIGNATURE-----
|
data.tar.gz.asc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
-----BEGIN PGP SIGNATURE-----
|
2
|
+
Version: GnuPG v1
|
3
|
+
|
4
|
+
iQEcBAABAgAGBQJWN9A3AAoJEGf2hZJktszzB68H/2fGaweofIk9JVSioqVP3hpi
|
5
|
+
JVpr/9fB84ax4MDFZnYpaYz9jwXdNdduyv/YShlOrIgVMJH6JjEa/rbUXPpvoQVe
|
6
|
+
NyEfMVutlmkwQE8AazQy7hSOrVJzRgvuMsVpzn+p3V58mgqxNLMx1nM4mW5VNqSM
|
7
|
+
mL2gOIEC6xrP9+EnHxxLqsRH+zGyWURPMk6IplrNjl7itzJ0laG2Pl3bzvWwKU+2
|
8
|
+
rBWwL4QRoXmMpAWFd8MP/oLgtY2P/1n0FAsqdkmF9dfaHmSlgcIMdmh6ThV3zIKE
|
9
|
+
28ADrdlH5ZOSi5Pn9/HbPoZNg16NLI0916WXb+V+LboY7GrfxNNiKe9wPB+4+yk=
|
10
|
+
=qgVL
|
11
|
+
-----END PGP SIGNATURE-----
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
plasper (0.1.0)
|
5
|
+
unicode (~> 0.4)
|
6
|
+
weighted-select (~> 1.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
diff-lcs (1.2.5)
|
12
|
+
rspec (3.3.0)
|
13
|
+
rspec-core (~> 3.3.0)
|
14
|
+
rspec-expectations (~> 3.3.0)
|
15
|
+
rspec-mocks (~> 3.3.0)
|
16
|
+
rspec-core (3.3.2)
|
17
|
+
rspec-support (~> 3.3.0)
|
18
|
+
rspec-expectations (3.3.1)
|
19
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
20
|
+
rspec-support (~> 3.3.0)
|
21
|
+
rspec-mocks (3.3.2)
|
22
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
23
|
+
rspec-support (~> 3.3.0)
|
24
|
+
rspec-support (3.3.0)
|
25
|
+
unicode (0.4.4.2)
|
26
|
+
weighted-select (1.0.0)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
plasper!
|
33
|
+
rspec (~> 3.3)
|
34
|
+
|
35
|
+
BUNDLED WITH
|
36
|
+
1.10.6
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Maxim Khan-Magomedov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
Talk Plasper
|
2
|
+
============
|
3
|
+
|
4
|
+
Tool that analyzes letter usage weights and reproduces syllables. The more statistics it has, the better texts are.
|
5
|
+
|
6
|
+
Installation
|
7
|
+
------------
|
8
|
+
|
9
|
+
`gem install plasper`
|
10
|
+
|
11
|
+
Usage
|
12
|
+
-----
|
13
|
+
|
14
|
+
`plasper [options] action`
|
15
|
+
|
16
|
+
-h, --help Show help
|
17
|
+
-t, --text-file path Path to file with text to analyze
|
18
|
+
-w, --weights-file path Path to file with initial weights in YAML format
|
19
|
+
-o, --output-file path Path to output file for dumping weights
|
20
|
+
|
21
|
+
Available options are
|
22
|
+
|
23
|
+
* `dump` (default) — dump weights on screen
|
24
|
+
* `talk` output one passage of text based on weights
|
25
|
+
* `chat` chat with your monsters from the Id.
|
26
|
+
|
27
|
+
If `-t` parameter is set, given file is analyzed and used for building weights.
|
28
|
+
|
29
|
+
If `-w` parameter is set, given file is parsed and used for building weights, too.
|
30
|
+
|
31
|
+
One can use both `-t` and `-w` parameters, weights will be added.
|
32
|
+
|
33
|
+
If `-o` parameter is set, resulting weights will be dumped as YAML into that file.
|
34
|
+
This can be useful in chat mode or for analyzing weights in texts from `-t` files.
|
35
|
+
|
36
|
+
Example of chat
|
37
|
+
---------------
|
38
|
+
|
39
|
+
$ plasper -o /tmp/stat/yml chat
|
40
|
+
Use ^D to exit.
|
41
|
+
Ego: Hello.
|
42
|
+
Id: Heloh
|
43
|
+
Ego: This is a version of English-speaking folks.
|
44
|
+
Id: Englo
|
45
|
+
Ego: Englo yourself.
|
46
|
+
Id: A yolis
|
47
|
+
Ego: Now I'll add several sentences. This will give more flexity.
|
48
|
+
Id: Fll akiow h-si thexiseve thingll. A wi eversiolkspexity moll adddd olof.
|
49
|
+
Ego: Several sentences are good. They add entropy. They increase weights!
|
50
|
+
Id: Tyoon willf wing shese ise. She adddddd ng akis tyofoflo.
|
51
|
+
Ego: If you give only word, it responds with word. If you give sentence,
|
52
|
+
plasper responds with sentence. If you give several sentences, it uses
|
53
|
+
passages.
|
54
|
+
Id: Foroures wincentht ong fo sese iseives gise eng seng. Ores fllou wes
|
55
|
+
tese thise a it ghesive reles. Wisaloll iveyous ongi wo.
|
56
|
+
Ego: Every input is analyzed.
|
57
|
+
Id: Wi isal mo renordds
|
58
|
+
|
59
|
+
So, one can see that it learns.
|
60
|
+
|
61
|
+
На русском тоже есть пример.
|
62
|
+
|
63
|
+
$ plasper -o /tmp/stat.yml chat
|
64
|
+
Use ^D to exit.
|
65
|
+
Ego: Привет.
|
66
|
+
Id: Привет
|
67
|
+
Ego: Как дела?
|
68
|
+
Id: Прив
|
69
|
+
Ego: Ты накурился что ли?
|
70
|
+
Id: Лсял тыде ли накака
|
71
|
+
Ego: Будут ли красные пятки торчать из грядки, если их достаточно хорошо закопать?
|
72
|
+
Id: Гропят
|
73
|
+
Ego: Это ты такое предложение высказываешь, значит?
|
74
|
+
Id: Будки эткрет
|
75
|
+
Ego: А если мы попробуем два предложения в абзаце? Так ведь прокатит, наверное? А?
|
76
|
+
Id: Чатоженорили ваеториеслое. Дь мыемы. Приеночтыся.
|
77
|
+
Ego: Ну уже хоть что-то получается. Нужно развивать и продвигать тему.
|
78
|
+
Id: Прн нуракаедьд поригацелазв просли а нуедь. Еся чияд вем пожемы мутоедли
|
79
|
+
патацешорч едла прятьвыет чачаза кужешьва хое тосядь. Акри муже пятое ак но
|
80
|
+
ткабу лаено в а тьпр игрето нивакрорят.
|
81
|
+
Ego: Осталось проработать момент с весами и правильным составлением слов, когда
|
82
|
+
нечего подставлять.
|
83
|
+
Id: Ты торенигрое тьнучт влутьнак атать ну
|
84
|
+
Ego: Но в целом круто вышло, пласпер.
|
85
|
+
Id: Кабужное знерядесто прутстымы азышо тобоеть
|
86
|
+
|
data/bin/plasper
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Plasper
|
4
|
+
class Options
|
5
|
+
attr_reader :text_file, :weights_file, :output_file, :action
|
6
|
+
|
7
|
+
DEFAULT_ACTION = 'dump'
|
8
|
+
VALID_ACTIONS = [DEFAULT_ACTION, 'talk', 'chat']
|
9
|
+
|
10
|
+
# Initialize with CLI arguments
|
11
|
+
#
|
12
|
+
# @param [Array] argv
|
13
|
+
def initialize(argv)
|
14
|
+
parse argv
|
15
|
+
@action = argv.last
|
16
|
+
@action = DEFAULT_ACTION unless VALID_ACTIONS.include? @action
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Parse given arguments
|
22
|
+
#
|
23
|
+
# @param [Array] argv
|
24
|
+
def parse(argv)
|
25
|
+
OptionParser.new do |options|
|
26
|
+
usage_and_help options
|
27
|
+
assign_text_file options
|
28
|
+
assign_weights_file options
|
29
|
+
assign_output_file options
|
30
|
+
|
31
|
+
begin
|
32
|
+
options.parse argv
|
33
|
+
rescue OptionParser::ParseError => error
|
34
|
+
STDERR.puts error.message, "\n", options
|
35
|
+
exit(-1)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Assign input text file path from options
|
41
|
+
#
|
42
|
+
# @param [OptionParser] options
|
43
|
+
def assign_text_file(options)
|
44
|
+
options.on('-t', '--text-file path', String, 'Path to file with text to analyze') do |path|
|
45
|
+
@text_file = path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Assign input weights file path from options
|
50
|
+
#
|
51
|
+
# @param [OptionParser] options
|
52
|
+
def assign_weights_file(options)
|
53
|
+
options.on('-w', '--weights-file path', String, 'Path to file with initial weights in YAML format') do |path|
|
54
|
+
@weights_file = path
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Assign output file path from options
|
59
|
+
#
|
60
|
+
# @param [OptionParser] options
|
61
|
+
def assign_output_file(options)
|
62
|
+
options.on('-o', '--output-file path', String, 'Path to output file for dumping weights') do |path|
|
63
|
+
@output_file = path
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Chunk with usage information and help
|
68
|
+
#
|
69
|
+
# @param [OptionParser] options
|
70
|
+
def usage_and_help(options)
|
71
|
+
options.banner = "Usage: plasper [options] action\n action: dump (default), talk or chat"
|
72
|
+
options.on('-h', '--help', 'Show this message') do
|
73
|
+
puts options
|
74
|
+
exit
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'unicode'
|
2
|
+
require 'weighted-select'
|
3
|
+
|
4
|
+
module Plasper
|
5
|
+
class Plasper
|
6
|
+
attr_reader :weights
|
7
|
+
|
8
|
+
SENTENCE_DELIMITER = /[?!.]/
|
9
|
+
|
10
|
+
# Prepares selectors and weights storage
|
11
|
+
def initialize
|
12
|
+
@weights = { count: {}, first: {}, next: {}, last: {} }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Analyze input and add appropriate part
|
16
|
+
#
|
17
|
+
# Determines if input is word, sentence or passage and adds it
|
18
|
+
#
|
19
|
+
# @param [String] input
|
20
|
+
def <<(input)
|
21
|
+
if input.index(/\s+/).nil?
|
22
|
+
word = normalize_word input
|
23
|
+
self.word = word unless word == ''
|
24
|
+
elsif input.scan(SENTENCE_DELIMITER).length < 2
|
25
|
+
self.sentence = input.gsub(SENTENCE_DELIMITER, '')
|
26
|
+
else
|
27
|
+
self.passage = input
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Analyze word
|
32
|
+
#
|
33
|
+
# Adds weights for first, next and last letters and letter count
|
34
|
+
#
|
35
|
+
# @param [String] word
|
36
|
+
def word=(word)
|
37
|
+
add_weight :count, :letter, word.length
|
38
|
+
add_weight :first, :letter, word[0]
|
39
|
+
(word.length - 1).times { |l| add_weight :next, word[l], word[l.succ] }
|
40
|
+
add_weight :last, word[-2], word[-1]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Generate word
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def word
|
47
|
+
letter_count = weighted(:count, :letter).to_i
|
48
|
+
if letter_count == 1
|
49
|
+
last_letter! nil
|
50
|
+
elsif letter_count > 0
|
51
|
+
result = first_letter
|
52
|
+
(letter_count - 2).times { result += next_letter!(result[-1]) }
|
53
|
+
result + last_letter!(result[-1])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Analyze sentence
|
58
|
+
#
|
59
|
+
# Splits sentence with whitespace delimiter, adds weight for word count and analyzes each word
|
60
|
+
#
|
61
|
+
# @param [String] sentence
|
62
|
+
def sentence=(sentence)
|
63
|
+
words = sentence.split(/\s+/)
|
64
|
+
add_weight :count, :word, words.length unless words.length < 1
|
65
|
+
words.each do |word|
|
66
|
+
normalized_word = normalize_word word
|
67
|
+
self.word = normalized_word unless normalized_word == ''
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Generate sentence
|
72
|
+
#
|
73
|
+
# @return [String]
|
74
|
+
def sentence
|
75
|
+
string = word_count.times.map { word }.join(' ')
|
76
|
+
string[0] = Unicode.upcase(string[0]) unless string.to_s == ''
|
77
|
+
string
|
78
|
+
end
|
79
|
+
|
80
|
+
# Analyze passage
|
81
|
+
#
|
82
|
+
# Splits passage with sentence-ending punctuation, adds sentence count weight and analyzes each sentence
|
83
|
+
#
|
84
|
+
# @param [String] passage
|
85
|
+
def passage=(passage)
|
86
|
+
sentences = passage.split(SENTENCE_DELIMITER).select { |sentence| sentence.chomp != '' }
|
87
|
+
sentences.each { |sentence| self.sentence = sentence }
|
88
|
+
add_weight :count, :sentence, sentences.count
|
89
|
+
end
|
90
|
+
|
91
|
+
# Generate passage
|
92
|
+
#
|
93
|
+
# @return [String]
|
94
|
+
def passage
|
95
|
+
sentence_count.times.map { sentence }.join('. ') + '.'
|
96
|
+
end
|
97
|
+
|
98
|
+
# Add weight
|
99
|
+
#
|
100
|
+
# Used for adding weights for counters, first, next and last letter.
|
101
|
+
# Valid types are :count, :first, :next and :last (@see #initialize)
|
102
|
+
# Group is either symbol (e.g. :letters, :words, :sentences, :letter), or string representing letter
|
103
|
+
# Item is integer (letter, word and sentence count) or string representing letter
|
104
|
+
# Weight is used for weighted-select in generation methods
|
105
|
+
#
|
106
|
+
# @param [Symbol] type
|
107
|
+
# @param [Symbol|String] group
|
108
|
+
# @param [String|Integer] item
|
109
|
+
# @param [Integer] weight
|
110
|
+
def add_weight(type, group, item, weight = 1)
|
111
|
+
@weights[type][group] ||= Hash.new(0)
|
112
|
+
|
113
|
+
@weights[type][group][item] += Integer weight
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def normalize_word(word)
|
119
|
+
Unicode.downcase word.gsub(/[^[:word:]'-]/u, '')
|
120
|
+
end
|
121
|
+
|
122
|
+
# Generate weighted-random value
|
123
|
+
#
|
124
|
+
# Type is :count, :first, :next or :last
|
125
|
+
# Group is symbol (for member count or first letter) or string representing letter
|
126
|
+
#
|
127
|
+
# @param [Symbol] type
|
128
|
+
# @param [Symbol|String] group
|
129
|
+
def weighted(type, group)
|
130
|
+
if @weights[type].has_key?(group)
|
131
|
+
selector = WeightedSelect::Selector.new @weights[type][group]
|
132
|
+
selector.select
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# Generate first letter
|
137
|
+
#
|
138
|
+
# @return [String]
|
139
|
+
def first_letter
|
140
|
+
weighted :first, :letter
|
141
|
+
end
|
142
|
+
|
143
|
+
# Generate next letter for current one
|
144
|
+
#
|
145
|
+
# @param [String] current_letter
|
146
|
+
# @return [String]
|
147
|
+
def next_letter(current_letter)
|
148
|
+
weighted :next, current_letter
|
149
|
+
end
|
150
|
+
|
151
|
+
# Generate next letter with fallback
|
152
|
+
#
|
153
|
+
# If there are no weights with next letters for current_letter,
|
154
|
+
# try to generate another first letter instead and use it
|
155
|
+
#
|
156
|
+
# @param [String] current_letter
|
157
|
+
# @return [String]
|
158
|
+
def next_letter!(current_letter)
|
159
|
+
next_letter(current_letter) || first_letter.to_s
|
160
|
+
end
|
161
|
+
|
162
|
+
# Generate last letter after penultimate letter
|
163
|
+
#
|
164
|
+
# @param [String] penultimate_letter
|
165
|
+
# @return [String]
|
166
|
+
def last_letter(penultimate_letter)
|
167
|
+
weighted :last, penultimate_letter
|
168
|
+
end
|
169
|
+
|
170
|
+
# Generate last letter with fallback to #next_letter!
|
171
|
+
#
|
172
|
+
# If there are no weights for last letter after given one, try to fall back to next_letter
|
173
|
+
#
|
174
|
+
# @param [String] penultimate_letter
|
175
|
+
# @return [String]
|
176
|
+
def last_letter!(penultimate_letter)
|
177
|
+
last_letter(penultimate_letter) || next_letter!(penultimate_letter)
|
178
|
+
end
|
179
|
+
|
180
|
+
# Weighted-randomly select word count
|
181
|
+
#
|
182
|
+
# Used when generating #sentence
|
183
|
+
#
|
184
|
+
# @return [Integer]
|
185
|
+
def word_count
|
186
|
+
weighted(:count, :word).to_i
|
187
|
+
end
|
188
|
+
|
189
|
+
# Weighted-randomly select sentence count
|
190
|
+
#
|
191
|
+
# Used when generating #passage
|
192
|
+
#
|
193
|
+
# @return [Integer]
|
194
|
+
def sentence_count
|
195
|
+
weighted(:count, :sentence).to_i
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require_relative 'plasper'
|
2
|
+
require_relative 'options'
|
3
|
+
|
4
|
+
module Plasper
|
5
|
+
class Runner
|
6
|
+
def initialize(argv)
|
7
|
+
@plasper = Plasper.new
|
8
|
+
@options = Options.new(argv)
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
import_weights @options.weights_file unless @options.weights_file.nil?
|
13
|
+
import_text @options.text_file unless @options.text_file.nil?
|
14
|
+
action = @options.action.to_sym
|
15
|
+
send action if respond_to? action, true
|
16
|
+
export_weights @options.output_file unless @options.output_file.nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def dump
|
22
|
+
dump_weights STDOUT
|
23
|
+
end
|
24
|
+
|
25
|
+
def talk
|
26
|
+
puts @plasper.passage
|
27
|
+
end
|
28
|
+
|
29
|
+
def chat
|
30
|
+
puts 'Use ^D to exit.'
|
31
|
+
print 'Ego: '
|
32
|
+
while (input = STDIN.gets)
|
33
|
+
@plasper << input
|
34
|
+
if input.index(/\s+/).nil?
|
35
|
+
output = @plasper.word
|
36
|
+
elsif input.scan(Plasper::SENTENCE_DELIMITER).length < 2
|
37
|
+
output = @plasper.sentence
|
38
|
+
else
|
39
|
+
output = @plasper.passage
|
40
|
+
end
|
41
|
+
|
42
|
+
puts " Id: #{output}"
|
43
|
+
print 'Ego: '
|
44
|
+
end
|
45
|
+
puts
|
46
|
+
end
|
47
|
+
|
48
|
+
def import_weights(path)
|
49
|
+
if File.exists? path
|
50
|
+
type, category = nil, nil
|
51
|
+
File.open(path).read.each_line do |line|
|
52
|
+
if line =~ /\A\S+:\s*\z/
|
53
|
+
type = line.gsub(/[:\s]/, '').to_sym
|
54
|
+
elsif line =~ /\A \S+:\s*\z/
|
55
|
+
category = line.gsub(/[\s:]/, '')
|
56
|
+
category = category.to_sym if %w(word sentence letter).include? category
|
57
|
+
elsif line =~ /\A \S*?:\s+\d+\s*\z/
|
58
|
+
if type.is_a?(Symbol) && !category.nil?
|
59
|
+
item, weight = line.strip.split(':')
|
60
|
+
@plasper.add_weight type, category, (item == '' ? nil : item), Integer(weight)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def import_text(path)
|
68
|
+
if File.exists? path
|
69
|
+
File.open(path).read.each_line { |line| @plasper << line }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def export_weights(path)
|
74
|
+
File.open(path, 'w') { |file| dump_weights file }
|
75
|
+
end
|
76
|
+
|
77
|
+
def dump_weights(output)
|
78
|
+
@plasper.weights.each do |type, type_data|
|
79
|
+
output.puts "#{type}:"
|
80
|
+
type_data.each do |category, item_data|
|
81
|
+
output.puts " #{category}:"
|
82
|
+
item_data.each { |item, data| output.puts " #{item}: #{data}" }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/plasper.rb
CHANGED
@@ -1,67 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'unicode'
|
2
|
+
require 'weighted-select'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
@passage_range = { 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 3, 6 => 2, 7 => 1, 8 => 1, 9 => 1 }
|
8
|
-
@vowels = { e: 1, u: 1, i: 1, o: 1, a: 1 }
|
9
|
-
@consonants = {
|
10
|
-
q: 1, w: 1, r: 2, t: 2, y: 2, p: 2, s: 3, d: 3, f: 4, g: 3,
|
11
|
-
h: 3, j: 3, k: 3, l: 2, z: 1, x: 1, c: 2, v: 2, b: 2, n: 2, m: 2
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
def word
|
16
|
-
word_length = weighted_select(@word_range).to_i
|
17
|
-
word, length = '', 0
|
18
|
-
while length < word_length
|
19
|
-
letter = rand(100) < 40 ? consonant : vowel
|
20
|
-
word += letter
|
21
|
-
length += 1
|
22
|
-
end
|
23
|
-
|
24
|
-
word
|
25
|
-
end
|
26
|
-
|
27
|
-
def sentence
|
28
|
-
sentence_length = weighted_select(@sentence_range).to_i
|
29
|
-
sentence, length = [], 0
|
30
|
-
while length < sentence_length
|
31
|
-
sentence << word
|
32
|
-
length += 1
|
33
|
-
end
|
34
|
-
|
35
|
-
sentence.join(' ').capitalize + '.'
|
36
|
-
end
|
37
|
-
|
38
|
-
def passage
|
39
|
-
passage_length = weighted_select(@passage_range).to_i
|
40
|
-
passage, length = [], 0
|
41
|
-
while length < passage_length
|
42
|
-
passage << sentence
|
43
|
-
length += 1
|
44
|
-
end
|
45
|
-
|
46
|
-
passage.join(' ')
|
47
|
-
end
|
48
|
-
|
49
|
-
def vowel
|
50
|
-
weighted_select @vowels
|
51
|
-
end
|
52
|
-
|
53
|
-
def consonant
|
54
|
-
weighted_select @consonants
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def weighted_select(rules)
|
60
|
-
buffer = []
|
61
|
-
rules.each do |item, weight|
|
62
|
-
weight.times { buffer << item }
|
63
|
-
end
|
64
|
-
|
65
|
-
buffer.sample.to_s
|
66
|
-
end
|
67
|
-
end
|
4
|
+
require_relative 'plasper/plasper'
|
5
|
+
require_relative 'plasper/options'
|
6
|
+
require_relative 'plasper/runner'
|
data/plasper.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'plasper/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'plasper'
|
7
|
+
spec.version = Plasper::VERSION
|
8
|
+
spec.date = Plasper::DATE
|
9
|
+
spec.summary = 'Plasper that talks'
|
10
|
+
spec.description = 'Texts generator that analyzes input and tries to imitate syllables'
|
11
|
+
spec.authors = ['Maxim Khan-Magomedov']
|
12
|
+
spec.email = 'maxim.km@gmail.com'
|
13
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
spec.homepage = 'https://github.com/ozgg/plasper'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
spec.has_rdoc = false
|
18
|
+
spec.add_development_dependency "rspec", '~> 3.3'
|
19
|
+
spec.add_runtime_dependency 'weighted-select', '~> 1.0'
|
20
|
+
spec.add_runtime_dependency 'unicode', '~> 0.4'
|
21
|
+
end
|
metadata
CHANGED
@@ -1,22 +1,76 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plasper
|
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
|
- Maxim Khan-Magomedov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
13
|
-
|
11
|
+
date: 2015-11-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: weighted-select
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: unicode
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.4'
|
55
|
+
description: Texts generator that analyzes input and tries to imitate syllables
|
14
56
|
email: maxim.km@gmail.com
|
15
57
|
executables: []
|
16
58
|
extensions: []
|
17
59
|
extra_rdoc_files: []
|
18
60
|
files:
|
61
|
+
- ".gitignore"
|
62
|
+
- ".rspec"
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- LICENSE
|
66
|
+
- README.md
|
67
|
+
- bin/plasper
|
68
|
+
- lib/Plasper/options.rb
|
69
|
+
- lib/Plasper/plasper.rb
|
70
|
+
- lib/Plasper/runner.rb
|
71
|
+
- lib/Plasper/version.rb
|
19
72
|
- lib/plasper.rb
|
73
|
+
- plasper.gemspec
|
20
74
|
homepage: https://github.com/ozgg/plasper
|
21
75
|
licenses:
|
22
76
|
- MIT
|
@@ -27,18 +81,18 @@ require_paths:
|
|
27
81
|
- lib
|
28
82
|
required_ruby_version: !ruby/object:Gem::Requirement
|
29
83
|
requirements:
|
30
|
-
- -
|
84
|
+
- - ">="
|
31
85
|
- !ruby/object:Gem::Version
|
32
86
|
version: '0'
|
33
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
88
|
requirements:
|
35
|
-
- -
|
89
|
+
- - ">="
|
36
90
|
- !ruby/object:Gem::Version
|
37
91
|
version: '0'
|
38
92
|
requirements: []
|
39
93
|
rubyforge_project:
|
40
|
-
rubygems_version: 2.
|
94
|
+
rubygems_version: 2.4.5.1
|
41
95
|
signing_key:
|
42
96
|
specification_version: 4
|
43
|
-
summary: Plasper
|
97
|
+
summary: Plasper that talks
|
44
98
|
test_files: []
|
metadata.gz.asc
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
-----BEGIN PGP SIGNATURE-----
|
2
|
+
Version: GnuPG v1
|
3
|
+
|
4
|
+
iQEcBAABAgAGBQJWN9AxAAoJEGf2hZJktszzBucIALbDD+oCs5MDxB2/UewP7vEk
|
5
|
+
FbM2re4jbAY+yMXbI/nFLH86+qn3LIIKWapln+4kErqZpLZ447vsusFqYkdxtvJI
|
6
|
+
4DuG54GZFteEP0TPM60H4WccrHA5MoDkM/P+Er7vf+vvioLWorzGFOVv4Ijf+XY8
|
7
|
+
dv/kc8+9CQrN7fODKhmbq/iKkZX5av1kZAuGD0FYzGHwv8EZENjE91lM1llzTMkV
|
8
|
+
0CRCazTkcH0wH5E4KbtF23iEPCUZ5/Mpa4giqFQzh5AePwxMpShfupYUAhuABk1r
|
9
|
+
rETIraKImQyAvM8VppPKODICNAJG5suaMBggzkQyIMCoV5OOBb1M+RoJFVOwKoI=
|
10
|
+
=1UxQ
|
11
|
+
-----END PGP SIGNATURE-----
|