girlfriend 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.
- data/LICENSE +21 -0
- data/README.md +95 -0
- data/bin/girlfriend +69 -0
- data/lib/girlfriend.rb +126 -0
- data/lib/girlfriend/ability/base.rb +15 -0
- data/lib/girlfriend/ability/finger.rb +11 -0
- data/lib/girlfriend/ability/talk.rb +10 -0
- data/lib/girlfriend/eliza/eliza.rb +218 -0
- data/lib/girlfriend/eliza/pat2.rb +21 -0
- data/lib/girlfriend/eliza/pat3.rb +20 -0
- data/lib/girlfriend/eliza/pat4.rb +47 -0
- data/lib/girlfriend/eliza/pat5.rb +22 -0
- data/lib/girlfriend/version.rb +3 -0
- data/test/test_girlfriend.rb +30 -0
- metadata +81 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2011, Mihail Szabolcs
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, 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,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
Girlfriend
|
2
|
+
==========
|
3
|
+
Having an installable, upgradable and removable girlfriend has never been so easy!
|
4
|
+
|
5
|
+
You've come to the right place at the right time, look no further and get started
|
6
|
+
right away.
|
7
|
+
|
8
|
+
Getting Started with your Girlfriend
|
9
|
+
------------------------------------
|
10
|
+
In order to `install` your girlfriend open a terminal window and type:
|
11
|
+
|
12
|
+
gem install girlfriend
|
13
|
+
|
14
|
+
If you want to `upgrade` your girlfriend to a later version type:
|
15
|
+
|
16
|
+
gem update girlfriend
|
17
|
+
|
18
|
+
Finally, to `remove` your girlfriend you have to type:
|
19
|
+
|
20
|
+
gem remove girlfriend
|
21
|
+
|
22
|
+
Pretty straightforward isn't it?
|
23
|
+
|
24
|
+
Interacting with your Girlfriend
|
25
|
+
--------------------------------
|
26
|
+
Once you have your girlfriend `installed` open a terminal window and type:
|
27
|
+
|
28
|
+
girlfriend --ability interactive
|
29
|
+
|
30
|
+
This will take you in `interactive mode` where you can start `talking` at once.
|
31
|
+
|
32
|
+
Teach and tweak your Girlfriend
|
33
|
+
-------------------------------
|
34
|
+
Most probably, you don't want your girlfriend to be just like anybody else's girlfriend, fear
|
35
|
+
not because this is easier than you might think.
|
36
|
+
|
37
|
+
Create a file named `~/.girlfriend/config.rb` and open it in your favorite text editor:
|
38
|
+
|
39
|
+
Girlfriend.configure do |config|
|
40
|
+
config.name = 'Valeria'
|
41
|
+
config.age = 23
|
42
|
+
config.hometown = 'Moscow, Russia'
|
43
|
+
config.school = 'Russian Academy of Economics'
|
44
|
+
config.hobbies = ['gaming','travelling','photography']
|
45
|
+
end
|
46
|
+
|
47
|
+
Be sure to `finger` her afterwards to see the results via `girlfriend --ability finger` .
|
48
|
+
|
49
|
+
By default your girlfriend has two abilities 'finger' and 'talk', you can always list
|
50
|
+
all her abilities via `girlfriend --abilities`.
|
51
|
+
|
52
|
+
Adding her a new ability is just as easy as configuring her and can be done by dropping a new
|
53
|
+
file let's say `~/.girlfriend/eat.rb`:
|
54
|
+
|
55
|
+
module Girlfriend
|
56
|
+
module Ability
|
57
|
+
class Eat < Base
|
58
|
+
def eat(input)
|
59
|
+
if input =~ /pizza/i
|
60
|
+
'I love pizza!'
|
61
|
+
elif input =~ /banana/i
|
62
|
+
'Uh-oh, yummy!!! Hehe!'
|
63
|
+
else
|
64
|
+
'Dude, I don\'t like that! Yuck!'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Girlfriend.register_ability :eat do |girl|
|
72
|
+
Girlfriend::Ability::Eat.new(girl)
|
73
|
+
end
|
74
|
+
|
75
|
+
Be sure to check out her list of abilities `girlfriend --abilities` in order to confirm
|
76
|
+
that she acknowledged her new ability.
|
77
|
+
|
78
|
+
Your girlfriend's current version number can be verified by `girlfriend --version`.
|
79
|
+
|
80
|
+
Contribute
|
81
|
+
----------
|
82
|
+
* Fork the project.
|
83
|
+
* Make your feature addition or bug fix.
|
84
|
+
* Send me a pull request. Bonus points for topic branches.
|
85
|
+
* Do **not** bump the version number.
|
86
|
+
|
87
|
+
License
|
88
|
+
-------
|
89
|
+
Copyright (c) 2011, Mihail Szabolcs
|
90
|
+
|
91
|
+
Girlfriend is provided **as-is** under the **MIT** license. For more information see LICENSE.
|
92
|
+
|
93
|
+
Credits
|
94
|
+
-------
|
95
|
+
* [paipr](https://github.com/olabini/paipr)
|
data/bin/girlfriend
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
|
+
|
5
|
+
require 'girlfriend'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
# Register User Defined Abilities
|
9
|
+
Dir[File.join(File.expand_path('~/.girlfriend'),'*.rb')].each do |ability|
|
10
|
+
require "#{ability}"
|
11
|
+
end
|
12
|
+
|
13
|
+
help = <<HELP
|
14
|
+
Girlfriend is an installable, upgradable and removable girlfriend.
|
15
|
+
|
16
|
+
usage: girlfriend [options]
|
17
|
+
|
18
|
+
Current abilities:
|
19
|
+
interactive - try talking to her in interactive mode
|
20
|
+
talk - try talking to her
|
21
|
+
finger - try fingering her
|
22
|
+
|
23
|
+
Examples:
|
24
|
+
girlfriend --ability talk --input 'Hey, Ruby :)'
|
25
|
+
|
26
|
+
Options:
|
27
|
+
HELP
|
28
|
+
|
29
|
+
if ARGV.size < 1
|
30
|
+
puts 'Invalid options. Run `girlfriend --help` for assistance.'
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
options = {}
|
35
|
+
opts = OptionParser.new do |opts|
|
36
|
+
opts.banner = help
|
37
|
+
|
38
|
+
opts.on('--ability [ability]', 'specify ability to use') do |ability|
|
39
|
+
options['ability'] = ability
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on('--input [input]', 'specify input text') do |input|
|
43
|
+
options['input'] = input
|
44
|
+
end
|
45
|
+
|
46
|
+
opts.on('--abilities', 'list all abilities') do
|
47
|
+
puts Girlfriend.abilities.map { |name, ability| [name] }.join(", ")
|
48
|
+
exit 0
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on('--version', 'show version information') do
|
52
|
+
puts Girlfriend::VERSION
|
53
|
+
exit 0
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
begin
|
58
|
+
opts.parse!
|
59
|
+
rescue OptionParser::InvalidOption => e
|
60
|
+
puts e.message
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
|
64
|
+
if options['ability'].nil?
|
65
|
+
puts 'Invalid options. Run `girlfriend --help` for assistance.'
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
puts Girlfriend.interact?(options['ability'].to_sym, options['input'].to_s)
|
data/lib/girlfriend.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'girlfriend/eliza/pat2'
|
2
|
+
require 'girlfriend/eliza/pat3'
|
3
|
+
require 'girlfriend/eliza/pat4'
|
4
|
+
require 'girlfriend/eliza/pat5'
|
5
|
+
require 'girlfriend/eliza/eliza'
|
6
|
+
require 'girlfriend/version'
|
7
|
+
require 'girlfriend/ability/base'
|
8
|
+
require 'girlfriend/ability/finger'
|
9
|
+
require 'girlfriend/ability/talk'
|
10
|
+
|
11
|
+
module Girlfriend
|
12
|
+
class GirlfriendError < StandardError; end
|
13
|
+
class << self
|
14
|
+
attr_accessor :name, :age, :hometown, :school, :hobbies, :reply
|
15
|
+
|
16
|
+
#
|
17
|
+
# Configure Girlfriend to suit your needs
|
18
|
+
#
|
19
|
+
# Girlfriend.configure do |config|
|
20
|
+
# config.name = 'Ruby'
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Configurables:
|
24
|
+
#
|
25
|
+
# [name = String] Girlfriend's name
|
26
|
+
# [age = Integer] Girlfriend's age
|
27
|
+
# [hometown = String] Girlfriend's hometown
|
28
|
+
# [school = String] Girlfriend's school
|
29
|
+
# [hobbies = Array] Girlfriend's hobbies
|
30
|
+
# [reply = String] Girlfriend's default reply text
|
31
|
+
#
|
32
|
+
def configure
|
33
|
+
yield self
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Returns an empty or existing array of abilities
|
38
|
+
#
|
39
|
+
def abilities
|
40
|
+
@abilities ||= {}
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# Registers a new Girlfriend ability
|
45
|
+
#
|
46
|
+
# Girlfriend.register_ability :talk do |girl|
|
47
|
+
# Girlfriend::Ability::Talk.new(girl)
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
def register_ability(name, &block)
|
51
|
+
abilities[name] = block
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Returns TRUE if the given ability exists, otherwise FALSE
|
56
|
+
#
|
57
|
+
def can?(name)
|
58
|
+
abilities.include? name
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Interact with Girlfriend
|
63
|
+
#
|
64
|
+
# name - name of an ability
|
65
|
+
# input - text input (default: '')
|
66
|
+
#
|
67
|
+
# if name is :interactive then it enters interactive mode, otherwise
|
68
|
+
# executes and returns immediately
|
69
|
+
#
|
70
|
+
# Returns the result of the interaction.
|
71
|
+
#
|
72
|
+
def interact?(name, input='')
|
73
|
+
if name == :interactive
|
74
|
+
interactive(input)
|
75
|
+
else
|
76
|
+
if can? name
|
77
|
+
ability = abilities[name].call(self)
|
78
|
+
ability.try? name, input
|
79
|
+
else
|
80
|
+
reply
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
#
|
88
|
+
# Internal helper for interactive mode
|
89
|
+
#
|
90
|
+
# input - text input
|
91
|
+
#
|
92
|
+
def interactive(input)
|
93
|
+
puts 'Say hi to ' + name + ' now or type `leave` to stop talking to her!'
|
94
|
+
|
95
|
+
while true
|
96
|
+
print 'Dude > '
|
97
|
+
input = gets.chomp
|
98
|
+
|
99
|
+
if input == 'leave'
|
100
|
+
break
|
101
|
+
else
|
102
|
+
puts name + ' > ' + interact?(:talk, input)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
name + ' > Bye dude ...'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
Girlfriend.configure do |config|
|
112
|
+
config.name = 'Ruby'
|
113
|
+
config.age = 21
|
114
|
+
config.hometown = 'New York'
|
115
|
+
config.school = 'Florida State University'
|
116
|
+
config.hobbies = ['gaming','cooking','photography','blogging']
|
117
|
+
config.reply = 'LOL Z DUDE YOU MAD?'
|
118
|
+
end
|
119
|
+
|
120
|
+
Girlfriend.register_ability :finger do |girl|
|
121
|
+
Girlfriend::Ability::Finger.new(girl)
|
122
|
+
end
|
123
|
+
|
124
|
+
Girlfriend.register_ability :talk do |girl|
|
125
|
+
Girlfriend::Ability::Talk.new(girl)
|
126
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Girlfriend
|
2
|
+
module Ability
|
3
|
+
class Finger < Girlfriend::Ability::Base
|
4
|
+
def finger(input)
|
5
|
+
output = "I am #{girl.name}, a #{girl.age} years old girl from #{girl.hometown} currently attending #{girl.school}.\n\n"
|
6
|
+
output += "When not studying, I love #{girl.hobbies.join(", ")} and talking to dudes just like YOU."
|
7
|
+
output
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
#
|
2
|
+
# Original Source: https://github.com/olabini/paipr
|
3
|
+
#
|
4
|
+
module Enumerable
|
5
|
+
def some?
|
6
|
+
self.each do |v|
|
7
|
+
result = yield v
|
8
|
+
return result if result
|
9
|
+
end
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Array
|
15
|
+
def random_elt
|
16
|
+
self[rand(self.length)]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Rule
|
21
|
+
attr_reader :pattern, :responses
|
22
|
+
|
23
|
+
def initialize(pattern, *responses)
|
24
|
+
@pattern, @responses = pattern, responses
|
25
|
+
end
|
26
|
+
|
27
|
+
ELIZA_RULES =
|
28
|
+
[
|
29
|
+
Rule.new(Pattern.new(%w(*x hello *y)),
|
30
|
+
"How do you do. Please state your problem"),
|
31
|
+
Rule.new(Pattern.new(%w(*x I want *y)),
|
32
|
+
"What would it mean if you got ?y?",
|
33
|
+
"Why do you want ?y?",
|
34
|
+
"Suppose you got ?y soon"),
|
35
|
+
Rule.new(Pattern.new(%w(*x if *y)),
|
36
|
+
"Do you really think it's likely that ?y? ",
|
37
|
+
"Do you wish that ?y?",
|
38
|
+
"What do you think about ?y?",
|
39
|
+
"Really-- if ?y?"),
|
40
|
+
Rule.new(Pattern.new(%w(*x no *y)),
|
41
|
+
"Why not?",
|
42
|
+
"You are being a bit negative",
|
43
|
+
"Are you saying \"NO\" just to be negative?"),
|
44
|
+
Rule.new(Pattern.new(%w(*x I was *y)),
|
45
|
+
"Were you really?",
|
46
|
+
"Perhaps I already knew you were ?y?",
|
47
|
+
"Why do you tell me you were ?y now?"),
|
48
|
+
Rule.new(Pattern.new(%w(*x I feel *y)),
|
49
|
+
"Do you often feel ?y?"),
|
50
|
+
Rule.new(Pattern.new(%w(*x I felt *y)),
|
51
|
+
"What other feelings do you have?"),
|
52
|
+
Rule.new(Pattern.new(%w(*x computer *y)),
|
53
|
+
"Do computers worry you?",
|
54
|
+
"What do you think about machines?",
|
55
|
+
"Why do you mention computers",
|
56
|
+
"What do you think machines have to do with your problem?"),
|
57
|
+
Rule.new(Pattern.new(%w(*x name *y)),
|
58
|
+
"I am not interested in names"),
|
59
|
+
Rule.new(Pattern.new(%w(*x sorry *y)),
|
60
|
+
"Please don't apologize",
|
61
|
+
"Apologies are not necessary",
|
62
|
+
"What feelings do you have when you apologize?"),
|
63
|
+
Rule.new(Pattern.new(%w(*x I remember *y)),
|
64
|
+
"Do you often think of ?y?",
|
65
|
+
"Does thinking of ?y bring anything else to mind?",
|
66
|
+
"What else do you remember?",
|
67
|
+
"Why do you recall ?y right now?",
|
68
|
+
"What in the present situation reminds you of ?y?",
|
69
|
+
"What is the connection between me and ?y?"),
|
70
|
+
Rule.new(Pattern.new(%w(*x do you remember *y)),
|
71
|
+
"Did you think I would forget ?y?",
|
72
|
+
"Why do you think I should recall ?y now?",
|
73
|
+
"What about ?y?",
|
74
|
+
"You mentioned ?y"),
|
75
|
+
Rule.new(Pattern.new(%w(*x I dreamt *y)),
|
76
|
+
"Really-- ?y?",
|
77
|
+
"Have you ever fantasized ?y while you were awake?",
|
78
|
+
"Have you dreamt ?y before?"),
|
79
|
+
Rule.new(Pattern.new(%w(*x dream about *y)),
|
80
|
+
"How do you feel about ?y in reality?"),
|
81
|
+
Rule.new(Pattern.new(%w(*x dream *y)),
|
82
|
+
"What does this dream suggest to you?",
|
83
|
+
"Do you dream often?",
|
84
|
+
"What persons appear in your dreams?",
|
85
|
+
"Don't you believe that dream has to do with your problem? "),
|
86
|
+
Rule.new(Pattern.new(%w(*x my mother *y)),
|
87
|
+
"Who else in your family ?y?",
|
88
|
+
"Tell me more about your family"),
|
89
|
+
Rule.new(Pattern.new(%w(*x my father *y)),
|
90
|
+
"Your father?",
|
91
|
+
"Does he influence you strongly?",
|
92
|
+
"What else comes to mind when you think of your father?"),
|
93
|
+
Rule.new(Pattern.new(%w(*x I am glad *y)),
|
94
|
+
"How have I helped you to be ?y?",
|
95
|
+
"What makes you happy just now?",
|
96
|
+
"Can you explain why you are suddenly ?y?"),
|
97
|
+
Rule.new(Pattern.new(%w(*x I am sad *y)),
|
98
|
+
"I am sorry to hear you are depressed",
|
99
|
+
"I'm sure it's not pleasant to be sad"),
|
100
|
+
Rule.new(Pattern.new(%w(*x are like *y)),
|
101
|
+
"What resemblance do you see between ?x and ?y?"),
|
102
|
+
Rule.new(Pattern.new(%w(*x is like *y)),
|
103
|
+
"In what way is it that ?y is like ?y?",
|
104
|
+
"What resemblance do you see?",
|
105
|
+
"Could there really be come connection?",
|
106
|
+
"How?"),
|
107
|
+
Rule.new(Pattern.new(%w(*x alike *y)),
|
108
|
+
"In what way?",
|
109
|
+
"What similarities are there?"),
|
110
|
+
Rule.new(Pattern.new(%w(*x same *y)),
|
111
|
+
"What other connections do you see?"),
|
112
|
+
Rule.new(Pattern.new(%w(*x was I *y)),
|
113
|
+
"What if you were ?y?",
|
114
|
+
"Do you think you were ?y?",
|
115
|
+
"What would it mean if you were ?y?"),
|
116
|
+
Rule.new(Pattern.new(%w(*x I am *y)),
|
117
|
+
"In what way are you ?y?",
|
118
|
+
"Do you want to be ?y?"),
|
119
|
+
Rule.new(Pattern.new(%w(*x am I *y)),
|
120
|
+
"Do you believe you are ?y?",
|
121
|
+
"Would you want to be ?y?",
|
122
|
+
"You wish I would tell you you are ?y",
|
123
|
+
"What would it mean if you were ?y?"),
|
124
|
+
Rule.new(Pattern.new(%w(*x am *y)),
|
125
|
+
"Why do you say 'AM'? ",
|
126
|
+
"I don't understand that"),
|
127
|
+
Rule.new(Pattern.new(%w(*x are you *y)),
|
128
|
+
"Why are you interested in whether I am ?y or not?",
|
129
|
+
"Would you prefer if I weren't ?y? ",
|
130
|
+
"Perhaps I am ?y in your fantasies?"),
|
131
|
+
Rule.new(Pattern.new(%w(*x you are *y)),
|
132
|
+
"What makes you think I am ?y?"),
|
133
|
+
Rule.new(Pattern.new(%w(*x because *y)),
|
134
|
+
"Is that the real reason?",
|
135
|
+
"What other reasons might there be?",
|
136
|
+
"Does that reason seem to explain anything else?"),
|
137
|
+
Rule.new(Pattern.new(%w(*x were you *y)),
|
138
|
+
"Perhaps I was ?y",
|
139
|
+
"What do you think?",
|
140
|
+
"What if I had been ?y"),
|
141
|
+
Rule.new(Pattern.new(%w(*x I can't *y)),
|
142
|
+
"Maybe you could ?y now",
|
143
|
+
"What if you could ?y?"),
|
144
|
+
Rule.new(Pattern.new(%w(*x I *y you *z)),
|
145
|
+
"Perhaps in your fantasy we ?y each other"),
|
146
|
+
Rule.new(Pattern.new(%w(*x why don't you *y)),
|
147
|
+
"Should you ?y yourself?",
|
148
|
+
"Do you believe I don't ?y? ",
|
149
|
+
"Perhaps I will ?y in good time"),
|
150
|
+
Rule.new(Pattern.new(%w(*x yes *y)),
|
151
|
+
"You seem quite positive",
|
152
|
+
"You are sure?",
|
153
|
+
"I understand"),
|
154
|
+
Rule.new(Pattern.new(%w(*x someone *y)),
|
155
|
+
"Can you be more specific?"),
|
156
|
+
Rule.new(Pattern.new(%w(*x everyone *y)),
|
157
|
+
"Surely not everyone?",
|
158
|
+
"Can you think of anyone in particular?",
|
159
|
+
"Who for example?",
|
160
|
+
"You are thinking of a special person"),
|
161
|
+
Rule.new(Pattern.new(%w(*x always *y)),
|
162
|
+
"Can you think of a specific example?",
|
163
|
+
"When?",
|
164
|
+
"What incident are you thinking of?",
|
165
|
+
"Really-- always?"),
|
166
|
+
Rule.new(Pattern.new(%w(*x what *y)),
|
167
|
+
"Why do you ask?",
|
168
|
+
"Does that question interest you?",
|
169
|
+
"What is it you really want to know?",
|
170
|
+
"What do you think?",
|
171
|
+
"What comes to your mind when you ask that?"),
|
172
|
+
Rule.new(Pattern.new(%w(*x perhaps *y)),
|
173
|
+
"You do not seem quite certain"),
|
174
|
+
Rule.new(Pattern.new(%w(*x are *y)),
|
175
|
+
"Did you think they might not be ?y?",
|
176
|
+
"Possibly they are ?y"),
|
177
|
+
Rule.new(Pattern.new(%w(*x)),
|
178
|
+
"Very interesting",
|
179
|
+
"I am not sure I understand you fully",
|
180
|
+
"What does that suggest to you?",
|
181
|
+
"Please continue",
|
182
|
+
"Go on",
|
183
|
+
"Do you feel strongly about discussing such things?")
|
184
|
+
]
|
185
|
+
end
|
186
|
+
|
187
|
+
module Eliza
|
188
|
+
class << self
|
189
|
+
def interact?(input, rules = Rule::ELIZA_RULES)
|
190
|
+
eliza_rule(input.downcase.split, rules)
|
191
|
+
end
|
192
|
+
|
193
|
+
def eliza_rule(input, rules)
|
194
|
+
rules.some? do |rule|
|
195
|
+
result = rule.pattern.match(input)
|
196
|
+
if result
|
197
|
+
switch_viewpoint(result).inject(rule.responses.random_elt) do |sum, repl|
|
198
|
+
sum.gsub(repl[0], repl[1].join(" "))
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def switch_viewpoint(words)
|
205
|
+
replacements = [%w(I you),
|
206
|
+
%w(you I),
|
207
|
+
%w(me you),
|
208
|
+
%w(am are)]
|
209
|
+
hash = {}
|
210
|
+
words.each do |key, val|
|
211
|
+
hash[key] = replacements.inject(val) do |sum, repl|
|
212
|
+
sum.map { |val| val == repl[0] ? repl[1] : val}
|
213
|
+
end
|
214
|
+
end
|
215
|
+
hash
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'enumerator'
|
2
|
+
class Pattern
|
3
|
+
def initialize(pattern)
|
4
|
+
@pattern = pattern.map do |p|
|
5
|
+
variable?(p) ? p : p.downcase
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Does pattern match input? Any variable can match anything
|
10
|
+
def match(input, variables = [], pattern = @pattern)
|
11
|
+
pattern.enum_for(:zip, input).all? do |p, i|
|
12
|
+
(p.is_a?(Array) && i.is_a?(Array) && match(i, variables, p)) ||
|
13
|
+
(variable?(p) && (variables << [p, i])) ||
|
14
|
+
p == i
|
15
|
+
end && variables
|
16
|
+
end
|
17
|
+
|
18
|
+
def variable?(pattern)
|
19
|
+
pattern.is_a?(String) && pattern[0] == ??
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Pattern
|
2
|
+
# Match pattern against input in the context of the bindings
|
3
|
+
def match(input, variables = {}, pattern = @pattern)
|
4
|
+
pattern.enum_for(:zip, input).all? do |p, i|
|
5
|
+
match_recurse(p, i, variables) ||
|
6
|
+
match_variable(p, i, variables) ||
|
7
|
+
p == i
|
8
|
+
end && variables
|
9
|
+
end
|
10
|
+
|
11
|
+
def match_recurse(p, i, bindings)
|
12
|
+
p.is_a?(Array) && i.is_a?(Array) && match(i, bindings, p)
|
13
|
+
end
|
14
|
+
|
15
|
+
def match_variable(p, i, bindings)
|
16
|
+
variable?(p) &&
|
17
|
+
((bindings[p].nil? && (bindings[p] = i)) ||
|
18
|
+
bindings[p] == i)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class Pattern
|
2
|
+
# Match pattern against input in the context of the bindings
|
3
|
+
def match(input, variables = {}, pattern = @pattern)
|
4
|
+
case
|
5
|
+
when variables.nil?
|
6
|
+
nil
|
7
|
+
when variable?(pattern)
|
8
|
+
match_variable(pattern, input, variables)
|
9
|
+
when pattern == input
|
10
|
+
variables
|
11
|
+
when segment_pattern?(pattern)
|
12
|
+
match_segment(pattern, input, variables)
|
13
|
+
when pattern.is_a?(Array) && input.is_a?(Array)
|
14
|
+
match(input[1..-1],
|
15
|
+
match(input[0], variables, pattern[0]),
|
16
|
+
pattern[1..-1])
|
17
|
+
else
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def match_variable(p, i, bindings)
|
23
|
+
(bindings[p].nil? && bindings.merge(p => i)) ||
|
24
|
+
(bindings[p] == i && bindings)
|
25
|
+
end
|
26
|
+
|
27
|
+
def segment_pattern?(p)
|
28
|
+
p.is_a?(Array) && p[0][0] == ?*
|
29
|
+
end
|
30
|
+
|
31
|
+
def match_segment(pattern, input, bindings, start = 0)
|
32
|
+
var = "?#{pattern[0][1..-1]}"
|
33
|
+
pat = pattern[1..-1]
|
34
|
+
if pat.nil? || pat.empty?
|
35
|
+
match_variable(var, input, bindings)
|
36
|
+
else
|
37
|
+
pos = input[start..-1].index(pat[0])
|
38
|
+
return nil unless pos
|
39
|
+
b2 = match(input[(start+pos)..-1], bindings, pat)
|
40
|
+
if b2.nil?
|
41
|
+
match_segment(pattern, input, bindings, start+1)
|
42
|
+
else
|
43
|
+
match_variable(var, input[0...(start+pos)], b2)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Pattern
|
2
|
+
def match_segment(pattern, input, bindings, start = 0)
|
3
|
+
var = "?#{pattern[0][1..-1]}"
|
4
|
+
pat = pattern[1..-1]
|
5
|
+
if pat.nil? || pat.empty?
|
6
|
+
match_variable(var, input, bindings)
|
7
|
+
else
|
8
|
+
pos = input[start..-1].index(pat[0])
|
9
|
+
return nil unless pos
|
10
|
+
|
11
|
+
b2 = match(input[(start+pos)..-1],
|
12
|
+
match_variable(var, input[0...(start+pos)], bindings),
|
13
|
+
pat)
|
14
|
+
|
15
|
+
if !b2
|
16
|
+
match_segment(pattern, input, bindings, start+1)
|
17
|
+
else
|
18
|
+
b2
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'girlfriend'
|
3
|
+
|
4
|
+
class GirlfriendTest < Test::Unit::TestCase
|
5
|
+
def test_version
|
6
|
+
assert_equal Girlfriend::VERSION, '0.1.0'
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_config
|
10
|
+
assert_equal Girlfriend.name, 'Ruby'
|
11
|
+
assert_equal Girlfriend.age, 21
|
12
|
+
assert_equal Girlfriend.hometown, 'New York'
|
13
|
+
assert_equal Girlfriend.school, 'Florida State University'
|
14
|
+
assert_equal Girlfriend.hobbies, ['gaming','cooking','photography','blogging']
|
15
|
+
assert_equal Girlfriend.reply, 'LOL Z DUDE YOU MAD?'
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_abilities
|
19
|
+
assert_equal Girlfriend.abilities.size, 2
|
20
|
+
assert_equal Girlfriend.can?(:talk), true
|
21
|
+
assert_equal Girlfriend.can?(:finger), true
|
22
|
+
assert_equal Girlfriend.can?(:eat), false
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_talk
|
26
|
+
assert_equal Girlfriend.interact?(:eat), Girlfriend.reply
|
27
|
+
assert_equal Girlfriend.interact?(:talk, 'hello'), 'How do you do. Please state your problem'
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: girlfriend
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Mihail Szabolcs
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-06-12 00:00:00 +03:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Girlfriend is an installable, upgradable and removeable girlfriend
|
23
|
+
email:
|
24
|
+
- szaby@szabster.net
|
25
|
+
executables:
|
26
|
+
- girlfriend
|
27
|
+
extensions: []
|
28
|
+
|
29
|
+
extra_rdoc_files: []
|
30
|
+
|
31
|
+
files:
|
32
|
+
- lib/girlfriend.rb
|
33
|
+
- lib/girlfriend/eliza/pat2.rb
|
34
|
+
- lib/girlfriend/eliza/pat5.rb
|
35
|
+
- lib/girlfriend/eliza/pat4.rb
|
36
|
+
- lib/girlfriend/eliza/pat3.rb
|
37
|
+
- lib/girlfriend/eliza/eliza.rb
|
38
|
+
- lib/girlfriend/ability/finger.rb
|
39
|
+
- lib/girlfriend/ability/talk.rb
|
40
|
+
- lib/girlfriend/ability/base.rb
|
41
|
+
- lib/girlfriend/version.rb
|
42
|
+
- README.md
|
43
|
+
- LICENSE
|
44
|
+
- test/test_girlfriend.rb
|
45
|
+
- bin/girlfriend
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://github.com/icebreaker/girlfriend
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
hash: 3
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
version: "0"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project: girlfriend
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: Having an installable, upgradable and removable girlfriend has never been so easy!
|
80
|
+
test_files:
|
81
|
+
- test/test_girlfriend.rb
|