koalemos 0.0.1
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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/koalemos.gemspec +71 -0
- data/lib/koalemos.rb +6 -0
- data/lib/koalemos/beginning_of_day.rb +14 -0
- data/lib/koalemos/blank.rb +67 -0
- data/lib/koalemos/commaify.rb +19 -0
- data/lib/koalemos/friendly_time.rb +45 -0
- data/lib/koalemos/full.rb +31 -0
- data/lib/koalemos/hash_union.rb +16 -0
- data/lib/koalemos/num_to_time.rb +59 -0
- data/lib/koalemos/odd.rb +13 -0
- data/lib/koalemos/rand.rb +427 -0
- data/lib/koalemos/round.rb +38 -0
- data/lib/koalemos/symbol_to_proc.rb +15 -0
- data/lib/koalemos/try.rb +13 -0
- data/lib/koalemos/uniq_by.rb +29 -0
- data/spec/koalemos_spec.rb +7 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +9 -0
- metadata +99 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Tal Atlas
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= koalemos
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
+
* Send me a pull request. Bonus points for topic branches.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2009 Tal Atlas. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "koalemos"
|
8
|
+
gem.summary = %Q{Some extensions for me in all my projects}
|
9
|
+
gem.description = %Q{Nothing here you'd be interested in}
|
10
|
+
gem.email = "me@talatlas.com"
|
11
|
+
gem.homepage = "http://github.com/Talby/koalemos"
|
12
|
+
gem.authors = ["Tal Atlas"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
gem.add_development_dependency "yard", ">= 0"
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'spec/rake/spectask'
|
23
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
24
|
+
spec.libs << 'lib' << 'spec'
|
25
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
26
|
+
end
|
27
|
+
|
28
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
29
|
+
spec.libs << 'lib' << 'spec'
|
30
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
31
|
+
spec.rcov = true
|
32
|
+
end
|
33
|
+
|
34
|
+
task :spec => :check_dependencies
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
begin
|
39
|
+
require 'yard'
|
40
|
+
YARD::Rake::YardocTask.new
|
41
|
+
rescue LoadError
|
42
|
+
task :yardoc do
|
43
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
44
|
+
end
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/koalemos.gemspec
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{koalemos}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Tal Atlas"]
|
12
|
+
s.date = %q{2009-12-26}
|
13
|
+
s.description = %q{Nothing here you'd be interested in}
|
14
|
+
s.email = %q{me@talatlas.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"koalemos.gemspec",
|
27
|
+
"lib/koalemos.rb",
|
28
|
+
"lib/koalemos/beginning_of_day.rb",
|
29
|
+
"lib/koalemos/blank.rb",
|
30
|
+
"lib/koalemos/commaify.rb",
|
31
|
+
"lib/koalemos/friendly_time.rb",
|
32
|
+
"lib/koalemos/full.rb",
|
33
|
+
"lib/koalemos/hash_union.rb",
|
34
|
+
"lib/koalemos/num_to_time.rb",
|
35
|
+
"lib/koalemos/odd.rb",
|
36
|
+
"lib/koalemos/rand.rb",
|
37
|
+
"lib/koalemos/round.rb",
|
38
|
+
"lib/koalemos/symbol_to_proc.rb",
|
39
|
+
"lib/koalemos/try.rb",
|
40
|
+
"lib/koalemos/uniq_by.rb",
|
41
|
+
"spec/koalemos_spec.rb",
|
42
|
+
"spec/spec.opts",
|
43
|
+
"spec/spec_helper.rb"
|
44
|
+
]
|
45
|
+
s.homepage = %q{http://github.com/Talby/koalemos}
|
46
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
47
|
+
s.require_paths = ["lib"]
|
48
|
+
s.rubygems_version = %q{1.3.5}
|
49
|
+
s.summary = %q{Some extensions for me in all my projects}
|
50
|
+
s.test_files = [
|
51
|
+
"spec/koalemos_spec.rb",
|
52
|
+
"spec/spec_helper.rb"
|
53
|
+
]
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
57
|
+
s.specification_version = 3
|
58
|
+
|
59
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
60
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
61
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
64
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
65
|
+
end
|
66
|
+
else
|
67
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
68
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
data/lib/koalemos.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Koalemos
|
2
|
+
class ::Time
|
3
|
+
unless method_defined?(:beginning_of_day)
|
4
|
+
def beginning_of_day
|
5
|
+
::Time.mktime(self.year,self.month,self.day)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.beginning_of_day
|
9
|
+
t = ::Time.now
|
10
|
+
::Time.mktime(t.year,t.month,t.day)
|
11
|
+
end
|
12
|
+
end#unless
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Koalemos
|
2
|
+
module Blank
|
3
|
+
module Object
|
4
|
+
def blank?
|
5
|
+
respond_to?(:empty?) ? empty? : !self
|
6
|
+
end
|
7
|
+
|
8
|
+
def present?
|
9
|
+
!blank?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module NilClass
|
14
|
+
def blank?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module FalseClass
|
20
|
+
def blank?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module TrueClass
|
26
|
+
def blank?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Array
|
32
|
+
def self.included(modul)
|
33
|
+
modul.module_eval do
|
34
|
+
alias_method :blank?, :empty?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module Hash
|
40
|
+
def self.included(modul)
|
41
|
+
modul.module_eval do
|
42
|
+
alias_method :blank?, :empty?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module String
|
48
|
+
def blank?
|
49
|
+
self !~ /\S/
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module Numeric
|
54
|
+
def blank?
|
55
|
+
false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
unless Object.respond_to?(:blank?)
|
61
|
+
for k in Blank.constants
|
62
|
+
Object.const_get(k).class_eval do
|
63
|
+
include Blank.const_get(k)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Koalemos
|
2
|
+
class ::Numeric
|
3
|
+
unless method_defined?(:commafy)
|
4
|
+
def commafy
|
5
|
+
to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class ::Float
|
11
|
+
unless method_defined?(:commafy)
|
12
|
+
def commafy
|
13
|
+
to_s.gsub(/\d+\./) do |s|
|
14
|
+
s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'num_to_time.rb')
|
2
|
+
|
3
|
+
module Koalemos
|
4
|
+
module FriendlyTime
|
5
|
+
def friendly(since = Time.now)
|
6
|
+
ago = since - self
|
7
|
+
case ago
|
8
|
+
when 0...1.minute
|
9
|
+
'seconds ago'
|
10
|
+
when 1.minute...2.minutes
|
11
|
+
'1 minute ago'
|
12
|
+
when 2.minutes...1.hour
|
13
|
+
"#{(ago.to_f/1.minute.to_f).ceil} minutes ago"
|
14
|
+
when 1.hour...2.hours
|
15
|
+
'1 hour ago'
|
16
|
+
when 2.hours...1.day
|
17
|
+
"#{(ago.to_f/1.hour.to_f).ceil} hours ago"
|
18
|
+
when 1.day...2.days
|
19
|
+
'1 day ago'
|
20
|
+
when 2.days...1.month
|
21
|
+
"#{(ago.to_f/1.day.to_f).ceil} days ago"
|
22
|
+
when 1.month...2.months
|
23
|
+
'1 month ago'
|
24
|
+
when 2.months...1.year
|
25
|
+
"#{(ago.to_f/1.month.to_f).ceil} months ago"
|
26
|
+
when 1.year...2.years
|
27
|
+
'1 year ago'
|
28
|
+
else
|
29
|
+
"#{(ago.to_f/1.year.to_f).ceil} years ago"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class ::Time
|
35
|
+
if !method_defined?(:friendly) && ::Numeric.method_defined?(:day)
|
36
|
+
include FriendlyTime
|
37
|
+
else
|
38
|
+
if ::Numeric.method_defined?(:day)
|
39
|
+
warn "#{self}#friendly is already defined. Could not include #{__FILE__}"
|
40
|
+
else
|
41
|
+
warn "#{self}#friendly could not be defined, Numeric days needs to be defined. Could not include #{__FILE__}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Koalemos
|
2
|
+
module Full
|
3
|
+
# Returns the object if it isn't blank (as in Object#blank?), otherwise it
|
4
|
+
# returns nil. If a block was given as an argument and the object isn't
|
5
|
+
# blank, the block is executed with the object as its first argument. If an
|
6
|
+
# argument +dispatch+ was given and the object wasn't blank the method
|
7
|
+
# given by dispatch is called on the object. This is the same as
|
8
|
+
# foo.full?(&:bar) in the previous block form.
|
9
|
+
def full?(dispatch = nil, *args)
|
10
|
+
if blank?
|
11
|
+
obj = nil
|
12
|
+
#elsif Module === dispatch # TODO
|
13
|
+
# dispatch.found?(self)
|
14
|
+
elsif dispatch
|
15
|
+
obj = __send__(dispatch, *args)
|
16
|
+
obj = nil if obj.blank?
|
17
|
+
else
|
18
|
+
obj = self
|
19
|
+
end
|
20
|
+
if block_given? and obj
|
21
|
+
yield obj
|
22
|
+
else
|
23
|
+
obj
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class ::Object
|
29
|
+
include Full
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Koalemos
|
2
|
+
module HashUnion
|
3
|
+
def |(other)
|
4
|
+
other = other.to_hash if other.respond_to?(:to_hash)
|
5
|
+
other.merge(self)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class ::Hash
|
10
|
+
if method_defined?(:|)
|
11
|
+
warn "#{self}#| already defined, didn't include at #{__FILE__}:#{__LINE__}"
|
12
|
+
else
|
13
|
+
include HashUnion
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Koalemos
|
2
|
+
module NumToTime
|
3
|
+
def minute
|
4
|
+
self * 60
|
5
|
+
end
|
6
|
+
alias_method :minutes, :minute
|
7
|
+
|
8
|
+
def hour
|
9
|
+
self * 3600
|
10
|
+
end
|
11
|
+
alias_method :hours, :hour
|
12
|
+
|
13
|
+
def day
|
14
|
+
self * 86400
|
15
|
+
end
|
16
|
+
alias_method :days, :day
|
17
|
+
|
18
|
+
def week
|
19
|
+
self * 604800
|
20
|
+
end
|
21
|
+
alias_method :weeks, :week
|
22
|
+
|
23
|
+
def month
|
24
|
+
self * 2592000
|
25
|
+
end
|
26
|
+
alias_method :months, :month
|
27
|
+
|
28
|
+
def year
|
29
|
+
self * 31536000
|
30
|
+
end
|
31
|
+
alias_method :years, :year
|
32
|
+
|
33
|
+
def ago
|
34
|
+
Time.now - to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
def from_now
|
38
|
+
Time.now + to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_time
|
42
|
+
Time.at(to_i)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class ::Numeric
|
47
|
+
unless method_defined?(:minute)
|
48
|
+
include NumToTime
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# class ::Float
|
53
|
+
# unless method_defined?(:minute)
|
54
|
+
# include NumToTime
|
55
|
+
# else
|
56
|
+
# warn "Time methods for #{self} already defined, didn't include at #{__FILE__}:#{__LINE__.to_i-2}"
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
end
|
data/lib/koalemos/odd.rb
ADDED
@@ -0,0 +1,427 @@
|
|
1
|
+
#
|
2
|
+
# = rand.rb -- library for picking random elements and shuffling
|
3
|
+
#
|
4
|
+
# Copyright (C) 2004 Ilmari Heikkinen <mailto:kig@misfiring.net>
|
5
|
+
#
|
6
|
+
# Documentation:: Christian Neukirchen <mailto:chneukirchen@gmail.com>
|
7
|
+
#
|
8
|
+
|
9
|
+
module Koalemos
|
10
|
+
module Rand
|
11
|
+
module Enumerable_
|
12
|
+
# Choose and return a random element of the Enumerable.
|
13
|
+
# [1, 2, 3, 4].pick #=> 2 (or 1, 3, 4)
|
14
|
+
def pick
|
15
|
+
entries.pick
|
16
|
+
end
|
17
|
+
|
18
|
+
# Return an array of the elements in random order.
|
19
|
+
# [1, 2, 3, 4].shuffle #=> [3, 4, 1, 2]
|
20
|
+
def shuffle
|
21
|
+
entries.shuffle
|
22
|
+
end
|
23
|
+
|
24
|
+
# Calls _block_ once for each element in _self_ in random order,
|
25
|
+
# passing that element as a parameter.
|
26
|
+
def each_random(&block)
|
27
|
+
shuffle.each(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Invokes _block_ once for each element of _self_ in random order.
|
31
|
+
# Creates a new array containing the values returned by the block.
|
32
|
+
def map_random(&block)
|
33
|
+
shuffle.map(&block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
module Array
|
39
|
+
# Choose and return a random element of _self_.
|
40
|
+
# [1, 2, 3, 4].pick #=> 2 (or 1, 3, 4)
|
41
|
+
def pick
|
42
|
+
self[pick_index]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Deletes a random element of _self_, returning that element.
|
46
|
+
# a = [1, 2, 3, 4]
|
47
|
+
# a.pick #=> 2
|
48
|
+
# a #=> [1, 3, 4]
|
49
|
+
def pick!
|
50
|
+
i = pick_index
|
51
|
+
rv = self[i]
|
52
|
+
delete_at(i)
|
53
|
+
rv
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return the index of an random element of _self_.
|
57
|
+
# ["foo", "bar", "baz"].pick_index #=> 1 (or 0, or 2)
|
58
|
+
def pick_index
|
59
|
+
rand(size)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Destructive pick_index. Delete a random element of _self_ and
|
63
|
+
# return its index.
|
64
|
+
# a = [11, 22, 33, 44]
|
65
|
+
# a.pick_index! #=> 2
|
66
|
+
# a #=> [11, 22, 44]
|
67
|
+
def pick_index!
|
68
|
+
i = pick_index
|
69
|
+
delete_at i
|
70
|
+
i
|
71
|
+
end
|
72
|
+
|
73
|
+
# Return an array of the elements in random order.
|
74
|
+
# [11, 22, 33, 44].shuffle #=> [33, 11, 44, 22]
|
75
|
+
def shuffle
|
76
|
+
sort_by{rand}
|
77
|
+
end
|
78
|
+
|
79
|
+
# Destructive shuffle. Arrange the elements of _self_ in new order.
|
80
|
+
# a = [11, 22, 33, 44]
|
81
|
+
# a.shuffle!
|
82
|
+
# a #=> [33, 11, 44, 22]
|
83
|
+
def shuffle!
|
84
|
+
sort!{rand <=> 0.5}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
module Hash
|
90
|
+
# Choose and return a random key-value pair of _self_.
|
91
|
+
# {:one => 1, :two => 2, :three => 3}.pick #=> [:one, 1]
|
92
|
+
def pick
|
93
|
+
k = keys.pick
|
94
|
+
[k, self[k]]
|
95
|
+
end
|
96
|
+
|
97
|
+
# Deletes a random key-value pair of _self_, returning that pair.
|
98
|
+
# a = {:one => 1, :two => 2, :three => 3}
|
99
|
+
# a.pick #=> [:two, 2]
|
100
|
+
# a #=> {:one => 1, :three => 3}
|
101
|
+
def pick!
|
102
|
+
rv = pick
|
103
|
+
delete rv.first
|
104
|
+
rv
|
105
|
+
end
|
106
|
+
|
107
|
+
# Return a random key of _self_.
|
108
|
+
# {:one => 1, :two => 2, :three => 3}.pick_key #=> :three
|
109
|
+
def pick_key
|
110
|
+
keys.pick
|
111
|
+
end
|
112
|
+
|
113
|
+
# Return a random value of _self_.
|
114
|
+
# {:one => 1, :two => 2, :three => 3}.pick_value #=> 3
|
115
|
+
def pick_value
|
116
|
+
values.pick
|
117
|
+
end
|
118
|
+
|
119
|
+
# Delete a random key-value pair of _self_ and return the key.
|
120
|
+
# a = {:one => 1, :two => 2, :three => 3}
|
121
|
+
# a.pick_key! #=> :two
|
122
|
+
# a #=> {:one => 1, :three => 3}
|
123
|
+
def pick_key!
|
124
|
+
pick!.first
|
125
|
+
end
|
126
|
+
|
127
|
+
# Delete a random key-value pair of _self_ and return the value.
|
128
|
+
# a = {:one => 1, :two => 2, :three => 3}
|
129
|
+
# a.pick_value! #=> 2
|
130
|
+
# a #=> {:one => 1, :three => 3}
|
131
|
+
def pick_value!
|
132
|
+
pick!.last
|
133
|
+
end
|
134
|
+
|
135
|
+
# Return the key-value pairs of _self_ with _keys_ and _values_
|
136
|
+
# shuffled independedly.
|
137
|
+
# {:one => 1, :two => 2, :three => 3}.shuffle_hash_pairs
|
138
|
+
# #=> [[:one, 3], [:two, 1], [:three, 2]]
|
139
|
+
def shuffle_hash_pairs
|
140
|
+
keys.shuffle.zip(values.shuffle)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Return a copy of _self_ with _values_ arranged in random order.
|
144
|
+
# {:one => 1, :two => 2, :three => 3}.shuffle_hash
|
145
|
+
# #=> {:two=>2, :three=>1, :one=>3}
|
146
|
+
def shuffle_hash
|
147
|
+
shuffled = {}
|
148
|
+
shuffle_hash_pairs.each{|k, v|
|
149
|
+
shuffled[k] = v
|
150
|
+
}
|
151
|
+
shuffled
|
152
|
+
end
|
153
|
+
|
154
|
+
# Destructive shuffle_hash. Arrange the values of _self_ in
|
155
|
+
# new, random order.
|
156
|
+
# h = {:one => 1, :two => 2, :three => 3}
|
157
|
+
# h.shuffle_hash!
|
158
|
+
# h #=> {:two=>2, :three=>1, :one=>3}
|
159
|
+
def shuffle_hash!
|
160
|
+
shuffle_hash_pairs.each{|k, v|
|
161
|
+
self[k] = v
|
162
|
+
}
|
163
|
+
self
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
|
168
|
+
module String
|
169
|
+
# Return the string with characters arranged in random order.
|
170
|
+
# "Ruby rules".shuffle_chars #=> "e lybRsuur"
|
171
|
+
def shuffle_chars
|
172
|
+
split(//).shuffle.join('')
|
173
|
+
end
|
174
|
+
|
175
|
+
# Destructive shuffle_chars. Arrange the characters of the string
|
176
|
+
# in new, random order.
|
177
|
+
# s = "Ruby rules".shuffle_chars
|
178
|
+
# s.shuffle_chars!
|
179
|
+
# s #=> "e lybRsuur"
|
180
|
+
def shuffle_chars!
|
181
|
+
self[0,size] = shuffle_chars
|
182
|
+
end
|
183
|
+
|
184
|
+
# Return a random byte of _self_.
|
185
|
+
# "Ruby rules".pick_byte #=> 121
|
186
|
+
def pick_byte
|
187
|
+
self[pick_index]
|
188
|
+
end
|
189
|
+
|
190
|
+
# Return a single-character string of a random character in _self_.
|
191
|
+
# "Ruby rules".pick_char #=> "y"
|
192
|
+
def pick_char
|
193
|
+
pick_byte.chr
|
194
|
+
end
|
195
|
+
|
196
|
+
# Destructive pick_char. Delete a random character of the string
|
197
|
+
# and return it as a single-character string.
|
198
|
+
# s = "Ruby rules"
|
199
|
+
# s.pick_char! #=> "y"
|
200
|
+
# s #=> "Rub rules"
|
201
|
+
def pick_char!
|
202
|
+
i = pick_index
|
203
|
+
rv = self[i,1]
|
204
|
+
self[i,1] = ""
|
205
|
+
rv
|
206
|
+
end
|
207
|
+
|
208
|
+
# Destructive pick_byte. Delete a random byte of _self_ and return it.
|
209
|
+
# s = "Ruby rules"
|
210
|
+
# s.pick_byte! #=> 121
|
211
|
+
# s #=> "Rub rules"
|
212
|
+
def pick_byte!
|
213
|
+
pick_char![0]
|
214
|
+
end
|
215
|
+
|
216
|
+
# Return a random byte index of _self_.
|
217
|
+
# "Ruby rules".pick_index #=> 3
|
218
|
+
def pick_index
|
219
|
+
rand(size)
|
220
|
+
end
|
221
|
+
|
222
|
+
# Destructive pick_index. Delete a random byte of _self_ and
|
223
|
+
# return it's index.
|
224
|
+
# s = "Ruby rules"
|
225
|
+
# s.pick_index #=> 3
|
226
|
+
# s #=> "Rub rules"
|
227
|
+
def pick_index!
|
228
|
+
i = pick_index
|
229
|
+
self[i,1] = ""
|
230
|
+
i
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
unless Array.respond_to?(:pick)
|
235
|
+
for k in Rand.constants
|
236
|
+
Object.const_get( k.gsub(/_/,'') ).class_eval do
|
237
|
+
include Rand.const_get(k)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
else
|
241
|
+
warn "random mixins already defined cannot be added from #{__FILE__}"
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
if __FILE__ == $0
|
249
|
+
|
250
|
+
require 'test/unit'
|
251
|
+
include Koalemos
|
252
|
+
|
253
|
+
module RandTestHelpers # :nodoc:
|
254
|
+
def picker(enum, enum_check, method, n=50)
|
255
|
+
(1..n).all?{ enum_check.include? enum.send(method) }
|
256
|
+
end
|
257
|
+
|
258
|
+
def try_shuffling(enum, enum_c, method)
|
259
|
+
rv = nil
|
260
|
+
10.times{
|
261
|
+
rv = enum.send method
|
262
|
+
break if rv != enum_c
|
263
|
+
}
|
264
|
+
rv
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
class RandArrayTest < Test::Unit::TestCase # :nodoc:
|
270
|
+
include RandTestHelpers
|
271
|
+
|
272
|
+
def ar
|
273
|
+
(0..99).to_a
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_pick
|
277
|
+
a = ar
|
278
|
+
results = (0...a.size).map{ a.pick }
|
279
|
+
assert true, results.all? {|r| a.include? r }
|
280
|
+
end
|
281
|
+
|
282
|
+
def test_pick!
|
283
|
+
a = ar
|
284
|
+
results = (0...a.size).map{ a.pick! }
|
285
|
+
assert true, results.sort == (0..99).to_a and a.empty?
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_pick_index
|
289
|
+
a = ar
|
290
|
+
results = (0...a.size).map{ a.pick_index }
|
291
|
+
assert true, results.all? {|r| r.between?(0, a.size-1) }
|
292
|
+
end
|
293
|
+
|
294
|
+
def test_pick_index!
|
295
|
+
a = ar
|
296
|
+
# side-effect-relying block; a.size = a.size-1 after pick_index!,
|
297
|
+
# so the picked index max value is the new a.size
|
298
|
+
assert true, (0...a.size).all?{ a.pick_index!.between?(0, a.size) } and a.empty?
|
299
|
+
end
|
300
|
+
|
301
|
+
def test_shuffle
|
302
|
+
a = ar
|
303
|
+
shuffled = try_shuffling(a, a, :shuffle)
|
304
|
+
assert true, shuffled.sort == a and shuffled != a
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_shuffle!
|
308
|
+
a = ar
|
309
|
+
try_shuffling(a, ar, :shuffle!)
|
310
|
+
assert true, a != ar and a.sort == ar
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
|
315
|
+
class RandHashTest < Test::Unit::TestCase # :nodoc:
|
316
|
+
include RandTestHelpers
|
317
|
+
|
318
|
+
def ha
|
319
|
+
Hash[*(1..100).to_a]
|
320
|
+
end
|
321
|
+
|
322
|
+
def test_pick
|
323
|
+
assert true, picker(ha, ha.entries, :pick)
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_pick!
|
327
|
+
h = ha
|
328
|
+
assert true, picker(h, ha.entries, :pick!) and h.empty?
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_pick_key
|
332
|
+
assert true, picker(ha, ha.keys, :pick_key)
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_pick_key!
|
336
|
+
h = ha
|
337
|
+
assert true, picker(h, ha.keys, :pick_key!) and h.empty?
|
338
|
+
end
|
339
|
+
|
340
|
+
def test_pick_value
|
341
|
+
assert true, picker(ha, ha.values, :pick_value)
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_pick_value!
|
345
|
+
h = ha
|
346
|
+
assert true, picker(h, ha.values, :pick_value!) and h.empty?
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_shuffle_hash
|
350
|
+
h = ha
|
351
|
+
hs = try_shuffling(ha, h, :shuffle_hash)
|
352
|
+
assert true, hs != h and (hs.keys + hs.values).sort == (h.keys + h.values).sort
|
353
|
+
end
|
354
|
+
|
355
|
+
def test_shuffle_hash!
|
356
|
+
h = ha
|
357
|
+
hs = ha
|
358
|
+
try_shuffling(hs, h, :shuffle_hash!)
|
359
|
+
assert true, hs != h and (hs.keys + hs.values).sort == (h.keys + h.values).sort
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_shuffle
|
363
|
+
h = ha
|
364
|
+
hs = try_shuffling(ha, h, :shuffle)
|
365
|
+
assert true, hs != h and hs.entries.sort == h.entries.sort
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
|
370
|
+
class RandStringTest < Test::Unit::TestCase # :nodoc:
|
371
|
+
include RandTestHelpers
|
372
|
+
|
373
|
+
def self.pick_tests(endings)
|
374
|
+
endings.each{|ending, compare_str_f|
|
375
|
+
define_method("test_pick#{ending}"){
|
376
|
+
s = str
|
377
|
+
assert true, picker(s, instance_eval(&compare_str_f), "pick#{ending}", s.size)
|
378
|
+
}
|
379
|
+
}
|
380
|
+
end
|
381
|
+
|
382
|
+
def self.pick_tests!(endings)
|
383
|
+
endings.each{|ending, compare_str_f|
|
384
|
+
define_method("test_pick#{ending}!"){
|
385
|
+
s = str
|
386
|
+
assert true, picker(s, instance_eval(&compare_str_f), "pick#{ending}!", s.size) and s.empty?
|
387
|
+
}
|
388
|
+
}
|
389
|
+
end
|
390
|
+
|
391
|
+
def str
|
392
|
+
(("a".."z").to_s + "\n") * 10
|
393
|
+
end
|
394
|
+
|
395
|
+
def test_shuffle
|
396
|
+
s = str
|
397
|
+
ss = try_shuffling(s, s.to_a, :shuffle)
|
398
|
+
assert true, ss != s.to_a and ss.sort == s.to_a.sort
|
399
|
+
end
|
400
|
+
|
401
|
+
def test_shuffle_chars
|
402
|
+
s = str
|
403
|
+
ss = try_shuffling(s, s.split(//), :shuffle_chars)
|
404
|
+
assert true, ss != s and ss.split(//).sort == s.split(//).sort
|
405
|
+
end
|
406
|
+
|
407
|
+
def test_shuffle_chars!
|
408
|
+
s = str
|
409
|
+
ss = str
|
410
|
+
try_shuffling(ss, s.split(//), :shuffle_chars!)
|
411
|
+
assert true, ss != s and ss.split(//).sort == s.split(//).sort
|
412
|
+
end
|
413
|
+
|
414
|
+
pick_tests({ "" => lambda{str.to_a},
|
415
|
+
:_char => lambda{str.split(//)},
|
416
|
+
:_byte => lambda{str.split(//).map{|c| c[0]}},
|
417
|
+
:_index => lambda{(0...str.size).to_a}
|
418
|
+
})
|
419
|
+
|
420
|
+
pick_tests!({ :_char => lambda{str.split(//)},
|
421
|
+
:_byte => lambda{str.split(//).map{|c| c[0]}},
|
422
|
+
:_index => lambda{(0...str.size).to_a}
|
423
|
+
})
|
424
|
+
end
|
425
|
+
|
426
|
+
|
427
|
+
end #if
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Koalemos
|
2
|
+
# A bit more versatile rounding for Ruby
|
3
|
+
module Round
|
4
|
+
def self.included(klass)
|
5
|
+
if klass.instance_method(:round)
|
6
|
+
klass.class_eval do
|
7
|
+
begin
|
8
|
+
remove_method :round
|
9
|
+
rescue NameError
|
10
|
+
end
|
11
|
+
end
|
12
|
+
super
|
13
|
+
else
|
14
|
+
raise NoMethodError, 'no round method found'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def round(places = 0)
|
19
|
+
unless Integer === places
|
20
|
+
raise TypeError, "argument places has to be an Integer"
|
21
|
+
end
|
22
|
+
if places < 0
|
23
|
+
max_places = -Math.log(self.abs + 1) / Math.log(10)
|
24
|
+
raise ArgumentError, "places has to be >= #{max_places.ceil}" if max_places > places
|
25
|
+
end
|
26
|
+
t = self
|
27
|
+
f = 10.0 ** places
|
28
|
+
t *= f
|
29
|
+
if t >= 0.0
|
30
|
+
t = (t + 0.5).floor
|
31
|
+
elsif t < 0.0
|
32
|
+
t = (t - 0.5).ceil
|
33
|
+
end
|
34
|
+
t /= f
|
35
|
+
t.nan? ? self : t
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/koalemos/try.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Koalemos
|
2
|
+
module UniqBy
|
3
|
+
def uniq_by(&b)
|
4
|
+
b ||= lambda { |x| x }
|
5
|
+
inject({}) { |h, e| h[b[e]] ||= e; h }.values
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ::Enumerable
|
10
|
+
if method_defined?(:uniq_by)
|
11
|
+
warn "#{self}#uniq_by already defined, didn't include at #{__FILE__}:#{__LINE__}"
|
12
|
+
else
|
13
|
+
include UniqBy
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class ::Array
|
18
|
+
if method_defined?(:uniq_by)
|
19
|
+
warn "#{self}#uniq_by already defined, didn't include at #{__FILE__}:#{__LINE__}"
|
20
|
+
else
|
21
|
+
include UniqBy
|
22
|
+
|
23
|
+
def uniq_by!(&b)
|
24
|
+
replace uniq_by(&b)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: koalemos
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tal Atlas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-26 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: yard
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description: Nothing here you'd be interested in
|
36
|
+
email: me@talatlas.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- LICENSE
|
43
|
+
- README.rdoc
|
44
|
+
files:
|
45
|
+
- .document
|
46
|
+
- .gitignore
|
47
|
+
- LICENSE
|
48
|
+
- README.rdoc
|
49
|
+
- Rakefile
|
50
|
+
- VERSION
|
51
|
+
- koalemos.gemspec
|
52
|
+
- lib/koalemos.rb
|
53
|
+
- lib/koalemos/beginning_of_day.rb
|
54
|
+
- lib/koalemos/blank.rb
|
55
|
+
- lib/koalemos/commaify.rb
|
56
|
+
- lib/koalemos/friendly_time.rb
|
57
|
+
- lib/koalemos/full.rb
|
58
|
+
- lib/koalemos/hash_union.rb
|
59
|
+
- lib/koalemos/num_to_time.rb
|
60
|
+
- lib/koalemos/odd.rb
|
61
|
+
- lib/koalemos/rand.rb
|
62
|
+
- lib/koalemos/round.rb
|
63
|
+
- lib/koalemos/symbol_to_proc.rb
|
64
|
+
- lib/koalemos/try.rb
|
65
|
+
- lib/koalemos/uniq_by.rb
|
66
|
+
- spec/koalemos_spec.rb
|
67
|
+
- spec/spec.opts
|
68
|
+
- spec/spec_helper.rb
|
69
|
+
has_rdoc: true
|
70
|
+
homepage: http://github.com/Talby/koalemos
|
71
|
+
licenses: []
|
72
|
+
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options:
|
75
|
+
- --charset=UTF-8
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
version:
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
version:
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.3.5
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: Some extensions for me in all my projects
|
97
|
+
test_files:
|
98
|
+
- spec/koalemos_spec.rb
|
99
|
+
- spec/spec_helper.rb
|