thorero 0.9.4
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/History.txt +1 -0
- data/LICENSE +20 -0
- data/Manifest +45 -0
- data/Manifest.txt +29 -0
- data/README.txt +3 -0
- data/Rakefile +180 -0
- data/lib/extlib.rb +32 -0
- data/lib/extlib/assertions.rb +8 -0
- data/lib/extlib/blank.rb +42 -0
- data/lib/extlib/class.rb +175 -0
- data/lib/extlib/hash.rb +410 -0
- data/lib/extlib/hook.rb +366 -0
- data/lib/extlib/inflection.rb +141 -0
- data/lib/extlib/lazy_array.rb +106 -0
- data/lib/extlib/logger.rb +202 -0
- data/lib/extlib/mash.rb +143 -0
- data/lib/extlib/module.rb +37 -0
- data/lib/extlib/object.rb +165 -0
- data/lib/extlib/object_space.rb +13 -0
- data/lib/extlib/pathname.rb +5 -0
- data/lib/extlib/pooling.rb +233 -0
- data/lib/extlib/rubygems.rb +38 -0
- data/lib/extlib/simple_set.rb +39 -0
- data/lib/extlib/string.rb +132 -0
- data/lib/extlib/struct.rb +8 -0
- data/lib/extlib/tasks/release.rb +11 -0
- data/lib/extlib/time.rb +12 -0
- data/lib/extlib/version.rb +3 -0
- data/lib/extlib/virtual_file.rb +10 -0
- data/spec/blank_spec.rb +85 -0
- data/spec/hash_spec.rb +524 -0
- data/spec/hook_spec.rb +1198 -0
- data/spec/inflection_spec.rb +50 -0
- data/spec/lazy_array_spec.rb +896 -0
- data/spec/mash_spec.rb +244 -0
- data/spec/module_spec.rb +58 -0
- data/spec/object_space_spec.rb +9 -0
- data/spec/object_spec.rb +98 -0
- data/spec/pooling_spec.rb +486 -0
- data/spec/simple_set_spec.rb +26 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/string_spec.rb +200 -0
- data/spec/struct_spec.rb +12 -0
- data/spec/time_spec.rb +16 -0
- data/spec/virtual_file_spec.rb +21 -0
- data/thorero.gemspec +147 -0
- metadata +146 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# The original of this file was copied for the ActiveSupport project which is
|
|
2
|
+
# part of the Ruby On Rails web-framework (http://rubyonrails.org)
|
|
3
|
+
#
|
|
4
|
+
# Methods have been modified or removed. English inflection is now provided via
|
|
5
|
+
# the english gem (http://english.rubyforge.org)
|
|
6
|
+
#
|
|
7
|
+
# sudo gem install english
|
|
8
|
+
#
|
|
9
|
+
gem 'english', '>=0.2.0'
|
|
10
|
+
require 'english/inflect'
|
|
11
|
+
|
|
12
|
+
English::Inflect.word 'postgres'
|
|
13
|
+
|
|
14
|
+
module Extlib
|
|
15
|
+
module Inflection
|
|
16
|
+
class << self
|
|
17
|
+
# Take an underscored name and make it into a camelized name
|
|
18
|
+
#
|
|
19
|
+
# @example
|
|
20
|
+
# "egg_and_hams".classify #=> "EggAndHam"
|
|
21
|
+
# "post".classify #=> "Post"
|
|
22
|
+
#
|
|
23
|
+
def classify(name)
|
|
24
|
+
camelize(singularize(name.to_s.sub(/.*\./, '')))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# By default, camelize converts strings to UpperCamelCase.
|
|
28
|
+
#
|
|
29
|
+
# camelize will also convert '/' to '::' which is useful for converting paths to namespaces
|
|
30
|
+
#
|
|
31
|
+
# @example
|
|
32
|
+
# "active_record".camelize #=> "ActiveRecord"
|
|
33
|
+
# "active_record/errors".camelize #=> "ActiveRecord::Errors"
|
|
34
|
+
#
|
|
35
|
+
def camelize(lower_case_and_underscored_word, *args)
|
|
36
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# The reverse of +camelize+. Makes an underscored form from the expression in the string.
|
|
41
|
+
#
|
|
42
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
|
43
|
+
#
|
|
44
|
+
# @example
|
|
45
|
+
# "ActiveRecord".underscore #=> "active_record"
|
|
46
|
+
# "ActiveRecord::Errors".underscore #=> active_record/errors
|
|
47
|
+
#
|
|
48
|
+
def underscore(camel_cased_word)
|
|
49
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
|
50
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
51
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
52
|
+
tr("-", "_").
|
|
53
|
+
downcase
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Capitalizes the first word and turns underscores into spaces and strips _id.
|
|
57
|
+
# Like titleize, this is meant for creating pretty output.
|
|
58
|
+
#
|
|
59
|
+
# @example
|
|
60
|
+
# "employee_salary" #=> "Employee salary"
|
|
61
|
+
# "author_id" #=> "Author"
|
|
62
|
+
def humanize(lower_case_and_underscored_word)
|
|
63
|
+
lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Removes the module part from the expression in the string
|
|
67
|
+
#
|
|
68
|
+
# @example
|
|
69
|
+
# "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
|
|
70
|
+
# "Inflections".demodulize #=> "Inflections"
|
|
71
|
+
def demodulize(class_name_in_module)
|
|
72
|
+
class_name_in_module.to_s.gsub(/^.*::/, '')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Create the name of a table like Rails does for models to table names. This method
|
|
76
|
+
# uses the pluralize method on the last word in the string.
|
|
77
|
+
#
|
|
78
|
+
# @example
|
|
79
|
+
# "RawScaledScorer".tableize #=> "raw_scaled_scorers"
|
|
80
|
+
# "egg_and_ham".tableize #=> "egg_and_hams"
|
|
81
|
+
# "fancyCategory".tableize #=> "fancy_categories"
|
|
82
|
+
def tableize(class_name)
|
|
83
|
+
pluralize(underscore(class_name))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Creates a foreign key name from a class name.
|
|
87
|
+
#
|
|
88
|
+
# @example
|
|
89
|
+
# "Message".foreign_key #=> "message_id"
|
|
90
|
+
# "Admin::Post".foreign_key #=> "post_id"
|
|
91
|
+
def foreign_key(class_name, key = "id")
|
|
92
|
+
underscore(demodulize(class_name.to_s)) << "_" << key.to_s
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Constantize tries to find a declared constant with the name specified
|
|
96
|
+
# in the string. It raises a NameError when the name is not in CamelCase
|
|
97
|
+
# or is not initialized.
|
|
98
|
+
#
|
|
99
|
+
# @example
|
|
100
|
+
# "Module".constantize #=> Module
|
|
101
|
+
# "Class".constantize #=> Class
|
|
102
|
+
def constantize(camel_cased_word)
|
|
103
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
|
104
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# The reverse of pluralize, returns the singular form of a word in a string.
|
|
111
|
+
# Wraps the English gem
|
|
112
|
+
#
|
|
113
|
+
# @example
|
|
114
|
+
# "posts".singularize #=> "post"
|
|
115
|
+
# "octopi".singularize #=> "octopus"
|
|
116
|
+
# "sheep".singluarize #=> "sheep"
|
|
117
|
+
# "word".singluarize #=> "word"
|
|
118
|
+
# "the blue mailmen".singularize #=> "the blue mailman"
|
|
119
|
+
# "CamelOctopi".singularize #=> "CamelOctopus"
|
|
120
|
+
#
|
|
121
|
+
def singularize(word)
|
|
122
|
+
English::Inflect.singular(word)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Returns the plural form of the word in the string.
|
|
126
|
+
#
|
|
127
|
+
# @example
|
|
128
|
+
# "post".pluralize #=> "posts"
|
|
129
|
+
# "octopus".pluralize #=> "octopi"
|
|
130
|
+
# "sheep".pluralize #=> "sheep"
|
|
131
|
+
# "words".pluralize #=> "words"
|
|
132
|
+
# "the blue mailman".pluralize #=> "the blue mailmen"
|
|
133
|
+
# "CamelOctopus".pluralize #=> "CamelOctopi"
|
|
134
|
+
#
|
|
135
|
+
def pluralize(word)
|
|
136
|
+
English::Inflect.plural(word)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
end # module Inflection
|
|
141
|
+
end # module Extlib
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
class LazyArray # borrowed partially from StrokeDB
|
|
2
|
+
instance_methods.each { |m| undef_method m unless %w[ __id__ __send__ send dup class object_id kind_of? respond_to? assert_kind_of should should_not instance_variable_set instance_variable_get ].include?(m) }
|
|
3
|
+
|
|
4
|
+
include Enumerable
|
|
5
|
+
|
|
6
|
+
# these methods should return self or nil
|
|
7
|
+
RETURN_SELF = [ :<<, :clear, :concat, :collect!, :each, :each_index,
|
|
8
|
+
:each_with_index, :freeze, :insert, :map!, :push, :replace,
|
|
9
|
+
:reject!, :reverse!, :reverse_each, :sort!, :unshift ]
|
|
10
|
+
|
|
11
|
+
RETURN_SELF.each do |method|
|
|
12
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
13
|
+
def #{method}(*args, &block)
|
|
14
|
+
lazy_load
|
|
15
|
+
results = @array.#{method}(*args, &block)
|
|
16
|
+
results.kind_of?(Array) ? self : results
|
|
17
|
+
end
|
|
18
|
+
EOS
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
(Array.public_instance_methods(false).map { |m| m.to_sym } - RETURN_SELF - [ :taguri= ]).each do |method|
|
|
22
|
+
class_eval <<-EOS, __FILE__, __LINE__
|
|
23
|
+
def #{method}(*args, &block)
|
|
24
|
+
lazy_load
|
|
25
|
+
@array.#{method}(*args, &block)
|
|
26
|
+
end
|
|
27
|
+
EOS
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def replace(other)
|
|
31
|
+
mark_loaded
|
|
32
|
+
@array.replace(other.entries)
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def clear
|
|
37
|
+
mark_loaded
|
|
38
|
+
@array.clear
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def eql?(other)
|
|
43
|
+
lazy_load
|
|
44
|
+
@array.eql?(other.entries)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
alias == eql?
|
|
48
|
+
|
|
49
|
+
def load_with(&block)
|
|
50
|
+
@load_with_proc = block
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def loaded?
|
|
55
|
+
@loaded == true
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def unload
|
|
59
|
+
clear
|
|
60
|
+
@loaded = false
|
|
61
|
+
self
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def respond_to?(method, include_private = false)
|
|
65
|
+
super || @array.respond_to?(method, include_private)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_proc
|
|
69
|
+
@load_with_proc
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def initialize(*args, &block)
|
|
75
|
+
@loaded = false
|
|
76
|
+
@load_with_proc = proc { |v| v }
|
|
77
|
+
@array = Array.new(*args, &block)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def initialize_copy(original)
|
|
81
|
+
@array = original.entries
|
|
82
|
+
load_with(&original)
|
|
83
|
+
mark_loaded if @array.any?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def lazy_load
|
|
87
|
+
return if loaded?
|
|
88
|
+
mark_loaded
|
|
89
|
+
@load_with_proc[self]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def mark_loaded
|
|
93
|
+
@loaded = true
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# delegate any not-explicitly-handled methods to @array, if possible.
|
|
97
|
+
# this is handy for handling methods mixed-into Array like group_by
|
|
98
|
+
def method_missing(method, *args, &block)
|
|
99
|
+
if @array.respond_to?(method)
|
|
100
|
+
lazy_load
|
|
101
|
+
@array.send(method, *args, &block)
|
|
102
|
+
else
|
|
103
|
+
super
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
require "time" # httpdate
|
|
2
|
+
# ==== Public Merb Logger API
|
|
3
|
+
#
|
|
4
|
+
# To replace an existing logger with a new one:
|
|
5
|
+
# Merb::Logger.set_log(log{String, IO},level{Symbol, String})
|
|
6
|
+
#
|
|
7
|
+
# Available logging levels are
|
|
8
|
+
# Merb::Logger::{ Fatal, Error, Warn, Info, Debug }
|
|
9
|
+
#
|
|
10
|
+
# Logging via:
|
|
11
|
+
# Merb.logger.fatal(message<String>,&block)
|
|
12
|
+
# Merb.logger.error(message<String>,&block)
|
|
13
|
+
# Merb.logger.warn(message<String>,&block)
|
|
14
|
+
# Merb.logger.info(message<String>,&block)
|
|
15
|
+
# Merb.logger.debug(message<String>,&block)
|
|
16
|
+
#
|
|
17
|
+
# Logging with autoflush:
|
|
18
|
+
# Merb.logger.fatal!(message<String>,&block)
|
|
19
|
+
# Merb.logger.error!(message<String>,&block)
|
|
20
|
+
# Merb.logger.warn!(message<String>,&block)
|
|
21
|
+
# Merb.logger.info!(message<String>,&block)
|
|
22
|
+
# Merb.logger.debug!(message<String>,&block)
|
|
23
|
+
#
|
|
24
|
+
# Flush the buffer to
|
|
25
|
+
# Merb.logger.flush
|
|
26
|
+
#
|
|
27
|
+
# Remove the current log object
|
|
28
|
+
# Merb.logger.close
|
|
29
|
+
#
|
|
30
|
+
# ==== Private Merb Logger API
|
|
31
|
+
#
|
|
32
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
|
33
|
+
# Merb::Logger.new(log{String, IO},level{Symbol, String})
|
|
34
|
+
module Extlib
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
attr_accessor :logger
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Logger
|
|
41
|
+
|
|
42
|
+
attr_accessor :level
|
|
43
|
+
attr_accessor :delimiter
|
|
44
|
+
attr_accessor :auto_flush
|
|
45
|
+
attr_reader :buffer
|
|
46
|
+
attr_reader :log
|
|
47
|
+
attr_reader :init_args
|
|
48
|
+
|
|
49
|
+
# ==== Notes
|
|
50
|
+
# Ruby (standard) logger levels:
|
|
51
|
+
# :fatal:: An unhandleable error that results in a program crash
|
|
52
|
+
# :error:: A handleable error condition
|
|
53
|
+
# :warn:: A warning
|
|
54
|
+
# :info:: generic (useful) information about system operation
|
|
55
|
+
# :debug:: low-level information for developers
|
|
56
|
+
Levels =
|
|
57
|
+
{
|
|
58
|
+
:fatal => 7,
|
|
59
|
+
:error => 6,
|
|
60
|
+
:warn => 4,
|
|
61
|
+
:info => 3,
|
|
62
|
+
:debug => 0
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
# Readies a log for writing.
|
|
68
|
+
#
|
|
69
|
+
# ==== Parameters
|
|
70
|
+
# log<IO, String>:: Either an IO object or a name of a logfile.
|
|
71
|
+
def initialize_log(log)
|
|
72
|
+
close if @log # be sure that we don't leave open files laying around.
|
|
73
|
+
|
|
74
|
+
if log.respond_to?(:write)
|
|
75
|
+
@log = log
|
|
76
|
+
elsif File.exist?(log)
|
|
77
|
+
@log = open(log, (File::WRONLY | File::APPEND))
|
|
78
|
+
@log.sync = true
|
|
79
|
+
else
|
|
80
|
+
FileUtils.mkdir_p(File.dirname(log)) unless File.directory?(File.dirname(log))
|
|
81
|
+
@log = open(log, (File::WRONLY | File::APPEND | File::CREAT))
|
|
82
|
+
@log.sync = true
|
|
83
|
+
@log.write("#{Time.now.httpdate} #{delimiter} info #{delimiter} Logfile created\n")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
public
|
|
88
|
+
|
|
89
|
+
# To initialize the logger you create a new object, proxies to set_log.
|
|
90
|
+
#
|
|
91
|
+
# ==== Parameters
|
|
92
|
+
# *args:: Arguments to create the log from. See set_logs for specifics.
|
|
93
|
+
def initialize(*args)
|
|
94
|
+
@init_args = args
|
|
95
|
+
set_log(*args)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Replaces an existing logger with a new one.
|
|
99
|
+
#
|
|
100
|
+
# ==== Parameters
|
|
101
|
+
# log<IO, String>:: Either an IO object or a name of a logfile.
|
|
102
|
+
# log_level<~to_sym>::
|
|
103
|
+
# The log level from, e.g. :fatal or :info. Defaults to :error in the
|
|
104
|
+
# production environment and :debug otherwise.
|
|
105
|
+
# delimiter<String>::
|
|
106
|
+
# Delimiter to use between message sections. Defaults to " ~ ".
|
|
107
|
+
# auto_flush<Boolean>::
|
|
108
|
+
# Whether the log should automatically flush after new messages are
|
|
109
|
+
# added. Defaults to false.
|
|
110
|
+
def set_log(log, log_level = nil, delimiter = " ~ ", auto_flush = false)
|
|
111
|
+
if log_level && Levels[log_level.to_sym]
|
|
112
|
+
@level = Levels[log_level.to_sym]
|
|
113
|
+
elsif Merb.environment == "production"
|
|
114
|
+
@level = Levels[:warn]
|
|
115
|
+
else
|
|
116
|
+
@level = Levels[:debug]
|
|
117
|
+
end
|
|
118
|
+
@buffer = []
|
|
119
|
+
@delimiter = delimiter
|
|
120
|
+
@auto_flush = auto_flush
|
|
121
|
+
|
|
122
|
+
initialize_log(log)
|
|
123
|
+
|
|
124
|
+
Merb.logger = self
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Flush the entire buffer to the log object.
|
|
128
|
+
def flush
|
|
129
|
+
return unless @buffer.size > 0
|
|
130
|
+
@log.write(@buffer.slice!(0..-1).to_s)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Close and remove the current log object.
|
|
134
|
+
def close
|
|
135
|
+
flush
|
|
136
|
+
@log.close if @log.respond_to?(:close) && !@log.tty?
|
|
137
|
+
@log = nil
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Appends a message to the log. The methods yield to an optional block and
|
|
141
|
+
# the output of this block will be appended to the message.
|
|
142
|
+
#
|
|
143
|
+
# ==== Parameters
|
|
144
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
145
|
+
#
|
|
146
|
+
# ==== Returns
|
|
147
|
+
# String:: The resulting message added to the log file.
|
|
148
|
+
def <<(string = nil)
|
|
149
|
+
message = ""
|
|
150
|
+
message << delimiter
|
|
151
|
+
message << string if string
|
|
152
|
+
message << "\n" unless message[-1] == ?\n
|
|
153
|
+
@buffer << message
|
|
154
|
+
flush if @auto_flush
|
|
155
|
+
|
|
156
|
+
message
|
|
157
|
+
end
|
|
158
|
+
alias :push :<<
|
|
159
|
+
|
|
160
|
+
# Generate the logging methods for Merb.logger for each log level.
|
|
161
|
+
Levels.each_pair do |name, number|
|
|
162
|
+
class_eval <<-LEVELMETHODS, __FILE__, __LINE__
|
|
163
|
+
|
|
164
|
+
# Appends a message to the log if the log level is at least as high as
|
|
165
|
+
# the log level of the logger.
|
|
166
|
+
#
|
|
167
|
+
# ==== Parameters
|
|
168
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
169
|
+
#
|
|
170
|
+
# ==== Returns
|
|
171
|
+
# self:: The logger object for chaining.
|
|
172
|
+
def #{name}(message = nil)
|
|
173
|
+
self << message if #{number} >= level
|
|
174
|
+
self
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Appends a message to the log if the log level is at least as high as
|
|
178
|
+
# the log level of the logger. The bang! version of the method also auto
|
|
179
|
+
# flushes the log buffer to disk.
|
|
180
|
+
#
|
|
181
|
+
# ==== Parameters
|
|
182
|
+
# string<String>:: The message to be logged. Defaults to nil.
|
|
183
|
+
#
|
|
184
|
+
# ==== Returns
|
|
185
|
+
# self:: The logger object for chaining.
|
|
186
|
+
def #{name}!(message = nil)
|
|
187
|
+
self << message if #{number} >= level
|
|
188
|
+
flush if #{number} >= level
|
|
189
|
+
self
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# ==== Returns
|
|
193
|
+
# Boolean:: True if this level will be logged by this logger.
|
|
194
|
+
def #{name}?
|
|
195
|
+
#{number} >= level
|
|
196
|
+
end
|
|
197
|
+
LEVELMETHODS
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
end
|