plasper 0.0.1 → 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
- 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-----
|