annoy 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +7 -0
- data/LICENSE.txt +19 -0
- data/README.rdoc +23 -0
- data/Rakefile +104 -0
- data/annoy.gemspec +56 -0
- data/lib/annoy.rb +297 -0
- metadata +84 -0
data/CHANGES.txt
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2009 Delano Mandelbaum, Solutious Inc
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
= Annoy - v0.5
|
2
|
+
|
3
|
+
All your system-independent infoz in one handy class.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Via Rubygems, one of:
|
8
|
+
|
9
|
+
$ sudo gem install annoy
|
10
|
+
$ sudo gem install delano-annoy --source http://gems.github.com/
|
11
|
+
|
12
|
+
or via download:
|
13
|
+
* annoy-latest.tar.gz[http://github.com/delano/annoy/tarball/latest]
|
14
|
+
* annoy-latest.zip[http://github.com/delano/annoy/zipball/latest]
|
15
|
+
|
16
|
+
|
17
|
+
== Credits
|
18
|
+
|
19
|
+
* Delano Mandelbaum (delano@solutious.com)
|
20
|
+
|
21
|
+
== License
|
22
|
+
|
23
|
+
See: LICENSE.txt
|
data/Rakefile
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/clean'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'hanna/rdoctask'
|
5
|
+
require 'fileutils'
|
6
|
+
include FileUtils
|
7
|
+
|
8
|
+
task :default => :package
|
9
|
+
|
10
|
+
# CONFIG =============================================================
|
11
|
+
|
12
|
+
# Change the following according to your needs
|
13
|
+
README = "README.rdoc"
|
14
|
+
CHANGES = "CHANGES.txt"
|
15
|
+
LICENSE = "LICENSE.txt"
|
16
|
+
|
17
|
+
# Files and directories to be deleted when you run "rake clean"
|
18
|
+
CLEAN.include [ 'pkg', '*.gem', '.config']
|
19
|
+
|
20
|
+
# Virginia assumes your project and gemspec have the same name
|
21
|
+
name = (Dir.glob('*.gemspec') || ['virginia']).first.split('.').first
|
22
|
+
load "#{name}.gemspec"
|
23
|
+
version = @spec.version
|
24
|
+
|
25
|
+
# That's it! The following defaults should allow you to get started
|
26
|
+
# on other things.
|
27
|
+
|
28
|
+
|
29
|
+
# TESTS/SPECS =========================================================
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
# INSTALL =============================================================
|
34
|
+
|
35
|
+
Rake::GemPackageTask.new(@spec) do |p|
|
36
|
+
p.need_tar = true if RUBY_PLATFORM !~ /mswin/
|
37
|
+
end
|
38
|
+
|
39
|
+
task :release => [ :rdoc, :package ]
|
40
|
+
task :install => [ :rdoc, :package ] do
|
41
|
+
sh %{sudo gem install pkg/#{name}-#{version}.gem}
|
42
|
+
end
|
43
|
+
task :uninstall => [ :clean ] do
|
44
|
+
sh %{sudo gem uninstall #{name}}
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# RUBYFORGE RELEASE / PUBLISH TASKS ==================================
|
49
|
+
|
50
|
+
if @spec.rubyforge_project
|
51
|
+
desc 'Publish website to rubyforge'
|
52
|
+
task 'publish:rdoc' => 'doc/index.html' do
|
53
|
+
sh "scp -rp doc/* rubyforge.org:/var/www/gforge-projects/#{name}/"
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Public release to rubyforge'
|
57
|
+
task 'publish:gem' => [:package] do |t|
|
58
|
+
sh <<-end
|
59
|
+
rubyforge add_release -o Any -a #{CHANGES} -f -n #{README} #{name} #{name} #{@spec.version} pkg/#{name}-#{@spec.version}.gem &&
|
60
|
+
rubyforge add_file -o Any -a #{CHANGES} -f -n #{README} #{name} #{name} #{@spec.version} pkg/#{name}-#{@spec.version}.tgz
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
# RUBY DOCS TASK ==================================
|
68
|
+
|
69
|
+
Rake::RDocTask.new do |t|
|
70
|
+
t.rdoc_dir = 'doc'
|
71
|
+
t.title = @spec.summary
|
72
|
+
t.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object'
|
73
|
+
t.options << '--charset' << 'utf-8'
|
74
|
+
t.rdoc_files.include(LICENSE)
|
75
|
+
t.rdoc_files.include(README)
|
76
|
+
t.rdoc_files.include(CHANGES)
|
77
|
+
#t.rdoc_files.include('bin/*')
|
78
|
+
t.rdoc_files.include('lib/**/*.rb')
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
#Hoe.new('rspec', Spec::VERSION::STRING) do |p|
|
85
|
+
# p.summary = Spec::VERSION::SUMMARY
|
86
|
+
# p.description = "Behaviour Driven Development for Ruby."
|
87
|
+
# p.rubyforge_name = 'rspec'
|
88
|
+
# p.developer('RSpec Development Team', 'rspec-devel@rubyforge.org')
|
89
|
+
# p.extra_dev_deps = [["cucumber",">= 0.1.13"]]
|
90
|
+
# p.remote_rdoc_dir = "rspec/#{Spec::VERSION::STRING}"
|
91
|
+
# p.rspec_options = ['--options', 'spec/spec.opts']
|
92
|
+
# p.history_file = 'History.rdoc'
|
93
|
+
# p.readme_file = 'README.rdoc'
|
94
|
+
# p.post_install_message = <<-POST_INSTALL_MESSAGE
|
95
|
+
##{'*'*50}
|
96
|
+
#
|
97
|
+
# Thank you for installing rspec-#{Spec::VERSION::STRING}
|
98
|
+
#
|
99
|
+
# Please be sure to read History.rdoc and Upgrade.rdoc
|
100
|
+
# for useful information about this release.
|
101
|
+
#
|
102
|
+
#{'*'*50}
|
103
|
+
#POST_INSTALL_MESSAGE
|
104
|
+
#end
|
data/annoy.gemspec
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
@spec = Gem::Specification.new do |s|
|
2
|
+
s.name = "annoy"
|
3
|
+
s.rubyforge_project = "annoy"
|
4
|
+
s.version = "0.5.0"
|
5
|
+
s.summary = "Annoy: Like your annoying friend that asks you questions all the time."
|
6
|
+
s.description = s.summary
|
7
|
+
s.author = "Delano Mandelbaum"
|
8
|
+
s.email = "delano@solutious.com"
|
9
|
+
s.homepage = "http://solutious.com/"
|
10
|
+
|
11
|
+
|
12
|
+
# = EXECUTABLES =
|
13
|
+
# The list of executables in your project (if any). Don't include the path,
|
14
|
+
# just the base filename.
|
15
|
+
s.executables = %w[]
|
16
|
+
|
17
|
+
# = DEPENDENCIES =
|
18
|
+
# Add all gem dependencies
|
19
|
+
#s.add_dependency ''
|
20
|
+
s.add_dependency 'highline', '>= 1.5.0'
|
21
|
+
|
22
|
+
# = MANIFEST =
|
23
|
+
# The complete list of files to be included in the release. When GitHub packages your gem,
|
24
|
+
# it doesn't allow you to run any command that accesses the filesystem. You will get an
|
25
|
+
# error. You can ask your VCS for the list of versioned files:
|
26
|
+
# git ls-files
|
27
|
+
# svn list -R
|
28
|
+
s.files = %w(
|
29
|
+
CHANGES.txt
|
30
|
+
LICENSE.txt
|
31
|
+
README.rdoc
|
32
|
+
Rakefile
|
33
|
+
lib/annoy.rb
|
34
|
+
annoy.gemspec
|
35
|
+
)
|
36
|
+
|
37
|
+
s.extra_rdoc_files = %w[README.rdoc LICENSE.txt]
|
38
|
+
s.has_rdoc = true
|
39
|
+
s.rdoc_options = ["--line-numbers", "--title", s.summary, "--main", "README.rdoc"]
|
40
|
+
s.require_paths = %w[lib]
|
41
|
+
s.rubygems_version = '1.3.0'
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
45
|
+
s.specification_version = 2
|
46
|
+
|
47
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
48
|
+
s.add_runtime_dependency(%q<RedCloth>, [">= 4.0.4"])
|
49
|
+
else
|
50
|
+
s.add_dependency(%q<RedCloth>, [">= 4.0.4"])
|
51
|
+
end
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<RedCloth>, [">= 4.0.4"])
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/lib/annoy.rb
ADDED
@@ -0,0 +1,297 @@
|
|
1
|
+
#---
|
2
|
+
# TODO: Use Matrix to give a more accurate annoyance factor
|
3
|
+
# TODO: Add trivia questions
|
4
|
+
#+++
|
5
|
+
|
6
|
+
require 'timeout'
|
7
|
+
require 'highline'
|
8
|
+
|
9
|
+
# = Annoy
|
10
|
+
#
|
11
|
+
# Like your annoying friend that asks you questions all the time.
|
12
|
+
#
|
13
|
+
# Rudy uses Annoy to present the user with a simple question before
|
14
|
+
# continuing with a destructive action.
|
15
|
+
#
|
16
|
+
class Annoy
|
17
|
+
|
18
|
+
attr_accessor :factor
|
19
|
+
attr_accessor :flavor
|
20
|
+
attr_accessor :answer
|
21
|
+
attr_accessor :writer
|
22
|
+
attr_accessor :period
|
23
|
+
attr_accessor :system
|
24
|
+
|
25
|
+
@@operators = {
|
26
|
+
:low => %w(+ -),
|
27
|
+
:medium => %w(* -),
|
28
|
+
:high => %w(& * -),
|
29
|
+
:insane => %w(** << | & *)
|
30
|
+
}.freeze
|
31
|
+
|
32
|
+
@@strlen = {
|
33
|
+
:low => 2,
|
34
|
+
:medium => 3,
|
35
|
+
:high => 4,
|
36
|
+
:insane => 32
|
37
|
+
}.freeze
|
38
|
+
|
39
|
+
@@randsize = {
|
40
|
+
:low => 10,
|
41
|
+
:medium => 12,
|
42
|
+
:high => 50,
|
43
|
+
:insane => 1000
|
44
|
+
}.freeze
|
45
|
+
|
46
|
+
@@period = 60.freeze # max seconds to wait
|
47
|
+
@@flavors = [:numeric, :string].freeze
|
48
|
+
@@skip = false # skip questions
|
49
|
+
|
50
|
+
# Calling this method tells Annoy to not prompt for
|
51
|
+
# a response. All questions will return true.
|
52
|
+
def Annoy.enable_skip; @@skip = true; end
|
53
|
+
# Tells annoy to prompt for a response.
|
54
|
+
def Annoy.disable_skip; @@skip = false; end
|
55
|
+
# Returns true of Annoy is in skip mode
|
56
|
+
def Annoy.skip?; @@skip; end
|
57
|
+
|
58
|
+
# * +factor+ annoyance factor, one of :low (default), :medium, :high, :insane
|
59
|
+
# * +flavor+ annoyance flavor, one of :rand (default), :numeric, string
|
60
|
+
# * +writer+ an IO object to write to. Default: STDERR
|
61
|
+
# * +period+ the amount of time to wait in seconds. Default: 60
|
62
|
+
def initialize(opts={:factor=>:medium, :flavor=>:rand, :writer=>STDOUT, :period=>nil})
|
63
|
+
@factor = opts[:factor]
|
64
|
+
@flavor = Annoy.get_flavor(opts[:flavor])
|
65
|
+
@writer = opts[:writer]
|
66
|
+
@period = opts[:period] || @@period
|
67
|
+
unless Annoy.respond_to?("#{@flavor}_question")
|
68
|
+
raise "Hey, hey, hey. I don't know that flavor! (#{@flavor})"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Generates and returns a question. The correct response is available
|
73
|
+
# as +@answer+.
|
74
|
+
def question
|
75
|
+
q, @answer =Annoy.question(@factor, @flavor)
|
76
|
+
q
|
77
|
+
end
|
78
|
+
|
79
|
+
# A wrapper for string_question and numberic_question
|
80
|
+
def Annoy.question(factor=:medium, flavor=:rand)
|
81
|
+
raise "Come on, you ruined the flavor!" unless flavor
|
82
|
+
Annoy.send("#{flavor}_question", factor)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Generates a random string
|
86
|
+
def Annoy.string_question(factor=:medium)
|
87
|
+
# Strings don't need to be evaluated so the answer is the
|
88
|
+
# same as the question.
|
89
|
+
str = strand @@strlen[factor]
|
90
|
+
[str,str]
|
91
|
+
end
|
92
|
+
|
93
|
+
# * Generates a rudimentary numeric equation in the form: (Integer OPERATOR Integer).
|
94
|
+
# * Returns [equation, answer]
|
95
|
+
def Annoy.numeric_question(factor=:medium)
|
96
|
+
equation = answer = 0
|
97
|
+
while answer < 10
|
98
|
+
vals = [rand(@@randsize[factor])+1,
|
99
|
+
@@operators[factor][ rand(@@operators[factor].size) ],
|
100
|
+
rand(@@randsize[factor])+1 ]
|
101
|
+
equation = "(%d %s %d)" % vals
|
102
|
+
answer = eval(equation)
|
103
|
+
end
|
104
|
+
[equation, answer]
|
105
|
+
end
|
106
|
+
|
107
|
+
# Prints a question to +writer+ and waits for a response on STDIN.
|
108
|
+
# It checks whether STDIN is connected a tty so it doesn't block on gets
|
109
|
+
# when there's no human around to annoy. It will return <b>TRUE</b> when
|
110
|
+
# STDIN is NOT connected to a tty (when STDIN.tty? returns false).
|
111
|
+
# * +msg+ The message to print. Default: "Please confirm."
|
112
|
+
# Returns true when the answer is correct, otherwise false.
|
113
|
+
def Annoy.challenge?(msg="Please confirm.", factor=:medium, flavor=:rand, writer=STDOUT, period=nil)
|
114
|
+
return true unless STDIN.tty? # Humans only!
|
115
|
+
return true if Annoy.skip?
|
116
|
+
begin
|
117
|
+
success = Timeout::timeout(period || @@period) do
|
118
|
+
flavor = Annoy.get_flavor(flavor)
|
119
|
+
question, answer = Annoy.question(factor, flavor)
|
120
|
+
msg = "#{msg} To continue, #{Annoy.verb(flavor)} #{question}: "
|
121
|
+
#writer.print msg
|
122
|
+
#if ![:medium, :high, :insane].member?(factor) && flavor == :numeric
|
123
|
+
#writer.print "(#{answer}) "
|
124
|
+
#writer.flush
|
125
|
+
#end
|
126
|
+
#response = Annoy.get_response(writer)
|
127
|
+
|
128
|
+
highline = HighLine.new
|
129
|
+
response = highline.ask(msg) { |q|
|
130
|
+
q.echo = '*' # Don't display response
|
131
|
+
q.overwrite = true # Erase the question afterwards
|
132
|
+
q.whitespace = :strip # Remove whitespace from the response
|
133
|
+
q.answer_type = Integer if flavor == :numeric
|
134
|
+
}
|
135
|
+
|
136
|
+
ret = (response == answer)
|
137
|
+
writer.puts "Incorrect" unless ret
|
138
|
+
ret
|
139
|
+
end
|
140
|
+
rescue Interrupt
|
141
|
+
writer.puts $/, "Giving up!"
|
142
|
+
false
|
143
|
+
rescue Annoy::GiveUp => ex
|
144
|
+
writer.puts $/, "Giving up!"
|
145
|
+
false
|
146
|
+
rescue Timeout::Error => ex
|
147
|
+
writer.puts $/, "Times up!"
|
148
|
+
false
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Runs a challenge with the message, "Are you sure?"
|
153
|
+
# See: Annoy.challenge?
|
154
|
+
def Annoy.are_you_sure?(factor=:medium, flavor=:rand, writer=STDOUT)
|
155
|
+
Annoy.challenge?("Are you sure?", factor, flavor, writer)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Runs a challenge with the message, "Proceed?"
|
159
|
+
# See: Annoy.challenge?
|
160
|
+
def Annoy.proceed?(factor=:medium, flavor=:rand, writer=STDOUT)
|
161
|
+
Annoy.challenge?("Proceed?", factor, flavor, writer)
|
162
|
+
end
|
163
|
+
|
164
|
+
# See: Annoy.challenge?
|
165
|
+
# Uses the value of @flavor, @factor, and @writer
|
166
|
+
def challenge?(msg="Please confirm.")
|
167
|
+
Annoy.challenge?(msg, @factor, @flavor, @writer)
|
168
|
+
end
|
169
|
+
|
170
|
+
# See: Annoy.pose_question
|
171
|
+
# Uses the value of @writer
|
172
|
+
def pose_question(msg, regexp)
|
173
|
+
Annoy.pose_question(msg, regexp, @writer)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Prints a question to writer and waits for a response on STDIN.
|
177
|
+
# It checks whether STDIN is connected a tty so it doesn't block on gets.
|
178
|
+
# when there's no human around to annoy. It will return <b>TRUE</b> when
|
179
|
+
# STDIN is NOT connected to a tty.
|
180
|
+
# * +msg+ The question to pose to the user
|
181
|
+
# * +regexp+ The regular expression to match the answer.
|
182
|
+
def Annoy.pose_question(msg, regexp, writer=STDOUT, period=nil)
|
183
|
+
return true unless STDIN.tty? # Only ask a question if there's a human
|
184
|
+
return true if Annoy.skip?
|
185
|
+
begin
|
186
|
+
success = Timeout::timeout(period || @@period) do
|
187
|
+
regexp &&= Regexp.new regexp
|
188
|
+
highline = HighLine.new
|
189
|
+
response = highline.ask(msg) { |q|
|
190
|
+
q.echo = '*' # Don't display response
|
191
|
+
q.overwrite = true # Erase the question afterwards
|
192
|
+
q.whitespace = :strip # Remove whitespace from the response
|
193
|
+
}
|
194
|
+
regexp.match(response)
|
195
|
+
end
|
196
|
+
rescue Timeout::Error => ex
|
197
|
+
writer.puts $/, "Times up!"
|
198
|
+
false
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
|
203
|
+
def Annoy.timed_display(msg, writer, period=nil)
|
204
|
+
return true unless STDIN.tty? # Only ask a question if there's a human
|
205
|
+
if Annoy.skip?
|
206
|
+
#writer.puts msg
|
207
|
+
return true
|
208
|
+
end
|
209
|
+
begin
|
210
|
+
period ||= @@period
|
211
|
+
success = Timeout::timeout(period) do
|
212
|
+
writer.puts "Message will display for #{period} seconds"
|
213
|
+
writer.print msg
|
214
|
+
writer.flush if writer.respond_to?(:flush)
|
215
|
+
sleep period+1
|
216
|
+
end
|
217
|
+
rescue Timeout::Error => ex
|
218
|
+
writer.print "\r" << ' '*msg.size
|
219
|
+
end
|
220
|
+
|
221
|
+
true
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
def Annoy.get_response(writer=STDOUT)
|
226
|
+
return true unless STDIN.tty? # Humans only
|
227
|
+
return true if Annoy.skip?
|
228
|
+
# TODO: Count the number of keystrokes to prevent copy/paste.
|
229
|
+
# We can probably use Highline.
|
230
|
+
# We likely need to be more specific but this will do for now.
|
231
|
+
#if ::SysInfo.new.os == :unix
|
232
|
+
# begin
|
233
|
+
# response = []
|
234
|
+
# char = nil
|
235
|
+
# system("stty raw -echo") # Raw mode, no echo
|
236
|
+
# while char != "\r" || response.size > 5
|
237
|
+
# char = STDIN.getc.chr
|
238
|
+
# writer.print char
|
239
|
+
# writer.flush
|
240
|
+
# response << char
|
241
|
+
# end
|
242
|
+
# writer.print "\n\r"
|
243
|
+
# response = response.join('')
|
244
|
+
# rescue => ex
|
245
|
+
# ensure
|
246
|
+
# system("stty -raw echo") # Reset terminal mode
|
247
|
+
# end
|
248
|
+
#else
|
249
|
+
response = (STDIN.gets || "")
|
250
|
+
#end
|
251
|
+
response.chomp.gsub(/["']/, '')
|
252
|
+
end
|
253
|
+
# Returns a verb appropriate to the flavor.
|
254
|
+
# * :numeric => resolve
|
255
|
+
# * :string => type
|
256
|
+
def Annoy.verb(flavor)
|
257
|
+
case flavor
|
258
|
+
when :numeric then "resolve"
|
259
|
+
when :string then "type"
|
260
|
+
else
|
261
|
+
nil
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
#
|
266
|
+
# Generates a string of random alphanumeric characters.
|
267
|
+
# * +len+ is the length, an Integer. Default: 8
|
268
|
+
# * +safe+ in safe-mode, ambiguous characters are removed (default: true):
|
269
|
+
# i l o 1 0
|
270
|
+
def Annoy.strand( len=8, safe=true )
|
271
|
+
chars = ("a".."z").to_a + ("0".."9").to_a
|
272
|
+
chars.delete_if { |v| %w(i l o 1 0).member?(v) } if safe
|
273
|
+
str = ""
|
274
|
+
1.upto(len) { |i| str << chars[rand(chars.size-1)] }
|
275
|
+
str
|
276
|
+
end
|
277
|
+
|
278
|
+
# * +f+ a prospective flavor name
|
279
|
+
def Annoy.get_flavor(f)
|
280
|
+
f.to_sym == :rand ? flavor_rand : f.to_sym
|
281
|
+
end
|
282
|
+
|
283
|
+
# Return a random flavor
|
284
|
+
def Annoy.flavor_rand
|
285
|
+
@@flavors[rand(@@flavors.size)]
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
end
|
290
|
+
|
291
|
+
# = Annoy::GiveUp
|
292
|
+
#
|
293
|
+
# This is what happens when you don't answer Annoy's questions.
|
294
|
+
class Annoy::GiveUp < RuntimeError
|
295
|
+
end
|
296
|
+
|
297
|
+
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: annoy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Delano Mandelbaum
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-07 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: highline
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.5.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: RedCloth
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.0.4
|
34
|
+
version:
|
35
|
+
description: "Annoy: Like your annoying friend that asks you questions all the time."
|
36
|
+
email: delano@solutious.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README.rdoc
|
43
|
+
- LICENSE.txt
|
44
|
+
files:
|
45
|
+
- CHANGES.txt
|
46
|
+
- LICENSE.txt
|
47
|
+
- README.rdoc
|
48
|
+
- Rakefile
|
49
|
+
- lib/annoy.rb
|
50
|
+
- annoy.gemspec
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://solutious.com/
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --line-numbers
|
58
|
+
- --title
|
59
|
+
- "Annoy: Like your annoying friend that asks you questions all the time."
|
60
|
+
- --main
|
61
|
+
- README.rdoc
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "0"
|
75
|
+
version:
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project: annoy
|
79
|
+
rubygems_version: 1.3.2
|
80
|
+
signing_key:
|
81
|
+
specification_version: 2
|
82
|
+
summary: "Annoy: Like your annoying friend that asks you questions all the time."
|
83
|
+
test_files: []
|
84
|
+
|