array_statistics 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/History.txt +4 -0
- data/Manifest.txt +18 -0
- data/PostInstall.txt +6 -0
- data/README.rdoc +55 -0
- data/Rakefile +26 -0
- data/config/website.yml.sample +2 -0
- data/lib/array_statistics.rb +331 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +71 -0
- data/test/test_array_statistics.rb +49 -0
- data/test/test_helper.rb +2 -0
- data/website/index.html +11 -0
- data/website/index.txt +83 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +95 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
PostInstall.txt
|
4
|
+
README.rdoc
|
5
|
+
Rakefile
|
6
|
+
config/website.yml.sample
|
7
|
+
lib/array_statistics.rb
|
8
|
+
script/console
|
9
|
+
script/destroy
|
10
|
+
script/generate
|
11
|
+
script/txt2html
|
12
|
+
test/test_array_statistics.rb
|
13
|
+
test/test_helper.rb
|
14
|
+
website/index.html
|
15
|
+
website/index.txt
|
16
|
+
website/javascripts/rounded_corners_lite.inc.js
|
17
|
+
website/stylesheets/screen.css
|
18
|
+
website/template.html.erb
|
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
= array_statistics
|
2
|
+
|
3
|
+
http://rubyforge.org/projects/array-statistic/
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Array Statistics adds statistical operations to the ruby Array class.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* Percentiles
|
12
|
+
* Quartiles
|
13
|
+
* Median
|
14
|
+
* Mean
|
15
|
+
* Sum
|
16
|
+
* Outliers
|
17
|
+
|
18
|
+
== SYNOPSIS:
|
19
|
+
|
20
|
+
Array Statistics adds statistical operations to the ruby Array class.
|
21
|
+
The operations work on arrays of numbers or, more interestingly, arrays of _things_.
|
22
|
+
Each method added to Array by this gem takes an optional block that defines the "value" on which to base the operation.
|
23
|
+
|
24
|
+
== REQUIREMENTS:
|
25
|
+
|
26
|
+
meh
|
27
|
+
|
28
|
+
== INSTALL:
|
29
|
+
|
30
|
+
sudo gem install array-statistics
|
31
|
+
|
32
|
+
== LICENSE:
|
33
|
+
|
34
|
+
(The MIT License)
|
35
|
+
|
36
|
+
Copyright (c) 2008 Bruce Goodwin
|
37
|
+
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
39
|
+
a copy of this software and associated documentation files (the
|
40
|
+
'Software'), to deal in the Software without restriction, including
|
41
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
42
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
43
|
+
permit persons to whom the Software is furnished to do so, subject to
|
44
|
+
the following conditions:
|
45
|
+
|
46
|
+
The above copyright notice and this permission notice shall be
|
47
|
+
included in all copies or substantial portions of the Software.
|
48
|
+
|
49
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
50
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
51
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
52
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
53
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
54
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
55
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
%w[rubygems rake rake/clean fileutils hoe newgem rubigen].each { |f| require f }
|
2
|
+
require File.dirname(__FILE__) + '/lib/array_statistics'
|
3
|
+
|
4
|
+
# Generate all the Rake tasks
|
5
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
6
|
+
$hoe = Hoe.new('array_statistics', ArrayStatistics::VERSION) do |p|
|
7
|
+
p.developer('Bruce Goodwin', 'rubybg@gmail.com')
|
8
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
9
|
+
p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
|
10
|
+
p.rubyforge_name = p.name # TODO this is default value
|
11
|
+
# p.extra_deps = [
|
12
|
+
# ['activesupport','>= 2.0.2'],
|
13
|
+
# ]
|
14
|
+
p.extra_dev_deps = [
|
15
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
16
|
+
]
|
17
|
+
|
18
|
+
p.spec_extras['rdoc_options'] = ['--main', Dir['README*'].first] # hopefully fixed in future hoe > 1.8
|
19
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
20
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
21
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
22
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'newgem/tasks' # load /tasks/*.rake
|
26
|
+
|
@@ -0,0 +1,331 @@
|
|
1
|
+
|
2
|
+
# no need for these yet... maybe later.
|
3
|
+
# $:.unshift(File.dirname(__FILE__)) unless
|
4
|
+
# $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
5
|
+
|
6
|
+
module ArrayStatistics
|
7
|
+
VERSION = '0.1.0'
|
8
|
+
end
|
9
|
+
class Array
|
10
|
+
@as_sort_dirty = true
|
11
|
+
@as_last_comparison_block = nil
|
12
|
+
|
13
|
+
# Get percent order statistic based on "order statistic" from here: http://mathworld.wolfram.com/topics/RankStatistics.html
|
14
|
+
# Given some percentage between 0 and 1 (inclusive) return the greatest value in the subarray of this array which contains
|
15
|
+
# the bottom percent_less_than values of this array.
|
16
|
+
#
|
17
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
18
|
+
# This block can be safely skipped if the array contains numbers.
|
19
|
+
def percentile(percent_less_than, &value_block) # :yields: element
|
20
|
+
value_block = proc{|element| element} unless block_given?
|
21
|
+
sort! do |x, y|
|
22
|
+
value_block.call(x) <=> value_block.call(y)
|
23
|
+
end
|
24
|
+
|
25
|
+
percent_less_than = 0 if percent_less_than < 0
|
26
|
+
return nil if percent_less_than == 0
|
27
|
+
percent_less_than = 1 if percent_less_than > 1
|
28
|
+
percentile_i = (percent_less_than * (length-1)).floor
|
29
|
+
return self[percentile_i]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get percent rank based on "statistical rank" from here:http://mathworld.wolfram.com/topics/RankStatistics.html
|
33
|
+
# Given some value, find the percentage of its rank in this array
|
34
|
+
# the number returned will be the number between 0 and 1 (inclusive) which represents the percentage of values
|
35
|
+
# in this array which are less than or equal to the value passed in.
|
36
|
+
#
|
37
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
38
|
+
# This block can be safely skipped if the array contains numbers.
|
39
|
+
def percentile_rank(value, &value_block) # :yields: element
|
40
|
+
value_block = proc{|element| element} unless block_given?
|
41
|
+
sort! do |x, y|
|
42
|
+
value_block.call(x) <=> value_block.call(y)
|
43
|
+
end
|
44
|
+
return 0.0 if value < value_block.call(self[0])
|
45
|
+
each_index do |i|
|
46
|
+
if(value_block.call(self[i]) > value)
|
47
|
+
|
48
|
+
return i.to_f/length
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return 1
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get the median value of this array.
|
55
|
+
#
|
56
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
57
|
+
# This block can be safely skipped if the array contains numbers.
|
58
|
+
def median(sort_required=true, &value_block) # :yields: element
|
59
|
+
return 0 if empty? #to reduce instances of calling math methods on nil.
|
60
|
+
value_block = proc{|element| element} unless block_given?
|
61
|
+
|
62
|
+
median_index_arr = median_indices(&value_block)
|
63
|
+
median_vals = median_index_arr.collect do |element_index|
|
64
|
+
value_block.call(self[element_index])
|
65
|
+
end
|
66
|
+
|
67
|
+
median_vals.average
|
68
|
+
end
|
69
|
+
|
70
|
+
# returns either a single or double-value array containing the index or surrounding indeces
|
71
|
+
#
|
72
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
73
|
+
# This block can be safely skipped if the array contains numbers.
|
74
|
+
def median_indices(sort_required=true, &value_block) # :yields: element
|
75
|
+
return 0 if length == 0
|
76
|
+
value_block = proc{|element| element} unless block_given?
|
77
|
+
if(sort_required)
|
78
|
+
sort! do |x, y|
|
79
|
+
value_block.call(x) <=> value_block.call(y)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
median_index_arr = [length / 2]
|
84
|
+
if(length % 2 == 0)
|
85
|
+
median_index_arr.unshift(median_index_arr[0]-1)
|
86
|
+
end
|
87
|
+
|
88
|
+
median_index_arr
|
89
|
+
end
|
90
|
+
|
91
|
+
#returns an array with 2 values. The values are the first and third quartile indices following the same rules as the results of the median_indices method
|
92
|
+
#
|
93
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
94
|
+
# This block can be safely skipped if the array contains numbers.
|
95
|
+
def quartile_indices(&value_block) # :yields: element
|
96
|
+
median_i = median_indices(&value_block)
|
97
|
+
low_end = median_i[0]
|
98
|
+
high_start = median_i[median_i.length() -1]
|
99
|
+
|
100
|
+
low_arr = self[0..low_end]
|
101
|
+
high_arr = self[high_start..-1]
|
102
|
+
|
103
|
+
q1_indices = low_arr.median_indices(false, &value_block)
|
104
|
+
q3_indices = high_arr.median_indices(false, &value_block)
|
105
|
+
q3_indices.collect! do |index|
|
106
|
+
index + high_start
|
107
|
+
end
|
108
|
+
return [q1_indices, q3_indices]
|
109
|
+
end
|
110
|
+
|
111
|
+
#returns an array containing all the outliers in this set
|
112
|
+
#
|
113
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
114
|
+
# This block can be safely skipped if the array contains numbers.
|
115
|
+
def outliers(quartile_range_factor=1.5, &value_block) # :yields: element
|
116
|
+
value_block = proc{|element| element} unless block_given?
|
117
|
+
outlier_arr = []
|
118
|
+
outlier_threshold_is = outlier_threshold_indices(quartile_range_factor, &value_block)
|
119
|
+
# puts("Outlier Thresholds Indeces = [#{outlier_threshold_is[0]} <=> #{outlier_threshold_is[1]}]")
|
120
|
+
outlier_arr << self[0..outlier_threshold_is[0]] unless outlier_threshold_is[0].nil?
|
121
|
+
# puts("upper outliers = #{self[outlier_threshold_is[1]..-1] }")
|
122
|
+
outlier_arr << self[outlier_threshold_is[1]..-1] unless outlier_threshold_is[1].nil?
|
123
|
+
return outlier_arr.flatten
|
124
|
+
end
|
125
|
+
|
126
|
+
#removes all the outliers from this set and returns them.
|
127
|
+
#
|
128
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
129
|
+
# This block can be safely skipped if the array contains numbers.
|
130
|
+
def remove_outliers!(quartile_range_factor=1.5, &value_block) # :yields: element
|
131
|
+
outlier_arr = []
|
132
|
+
outlier_threshold_is = outlier_threshold_indices(quartile_range_factor, &value_block)
|
133
|
+
|
134
|
+
outlier_arr = outlier_arr + self.slice!(0..outlier_threshold_is[0]) unless outlier_threshold_is[0].nil?
|
135
|
+
#the preceeding slice!() will, of course shift the upper outlier threshold index down
|
136
|
+
high_outlier_index_offset = (outlier_threshold_is[0].nil?)? 0 : outlier_threshold_is[0] + 1
|
137
|
+
outlier_arr = outlier_arr + self.slice!(outlier_threshold_is[1]-high_outlier_index_offset..-1) unless outlier_threshold_is[1].nil?
|
138
|
+
return outlier_arr
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns an array with two values.
|
142
|
+
# The first value is the index of the last low outlier in this sorted array (this array will be sorted as a side-effect of this method)
|
143
|
+
# or nil if there are no low-end outliers
|
144
|
+
# The second value is the index of the first high outlier in this sorted array or nil if there are no high-end outliers
|
145
|
+
#
|
146
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
147
|
+
# This block can be safely skipped if the array contains numbers.
|
148
|
+
def outlier_threshold_indices(quartile_range_factor=1.5, &value_block) # :yields: element
|
149
|
+
value_block = proc{|element| element} unless block_given?
|
150
|
+
thresholds = outlier_thresholds(quartile_range_factor, &value_block) #this sorts self!
|
151
|
+
low_index = -1
|
152
|
+
while(value_block.call(self[low_index +1] ) < thresholds[0]) do
|
153
|
+
low_index = low_index + 1
|
154
|
+
end
|
155
|
+
low_index = nil if(low_index == -1)
|
156
|
+
|
157
|
+
high_index = length
|
158
|
+
while(value_block.call(self[high_index -1] ) > thresholds[1]) do
|
159
|
+
high_index = high_index - 1
|
160
|
+
end
|
161
|
+
high_index = nil if(high_index == length)
|
162
|
+
return [low_index, high_index]
|
163
|
+
end
|
164
|
+
|
165
|
+
#returns an array with two values:
|
166
|
+
# The first value is the low outlier threshhold for this data set
|
167
|
+
# The second value is the high outlier threshhold for this data set
|
168
|
+
#
|
169
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
170
|
+
# This block can be safely skipped if the array contains numbers.
|
171
|
+
def outlier_thresholds(quartile_range_factor=1.5, &value_block) # :yields: element
|
172
|
+
value_block = proc{|element| element} unless block_given?
|
173
|
+
|
174
|
+
quartile_is = quartile_indices(&value_block)
|
175
|
+
q1 = quartile_is[0].collect do |element_index|
|
176
|
+
value_block.call(self[element_index])
|
177
|
+
end
|
178
|
+
q1 = q1.average
|
179
|
+
|
180
|
+
q3 = quartile_is[1].collect do |element_index|
|
181
|
+
value_block.call(self[element_index])
|
182
|
+
end
|
183
|
+
q3 = q3.average
|
184
|
+
|
185
|
+
interquartile_range = q3-q1
|
186
|
+
# puts("Interquartile Range = [#{q1} <=> #{q3}], quartile range factor: #{quartile_range_factor}")
|
187
|
+
low_outlier_threshold = q1 - (interquartile_range * quartile_range_factor)
|
188
|
+
high_outlier_threshold = q3 + (interquartile_range * quartile_range_factor)
|
189
|
+
# puts("Outlier Thresholds = [#{low_outlier_threshold} <=> #{high_outlier_threshold}]")
|
190
|
+
|
191
|
+
return [low_outlier_threshold, high_outlier_threshold]
|
192
|
+
end
|
193
|
+
|
194
|
+
# Returns the average of the values in this array.
|
195
|
+
#
|
196
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
197
|
+
# This block can be safely skipped if the array contains numbers.
|
198
|
+
def average(&value_block) # :yields: element
|
199
|
+
s = sum(&value_block)
|
200
|
+
s = s.to_f if s.integer?
|
201
|
+
s / length
|
202
|
+
end
|
203
|
+
|
204
|
+
# Returns the sum of all the values in this array.
|
205
|
+
#
|
206
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
207
|
+
# This block can be safely skipped if the array contains numbers.
|
208
|
+
def sum(&value_block) # :yields: element
|
209
|
+
value_block = proc{|element| element} unless block_given?
|
210
|
+
s = 0
|
211
|
+
each do |element|
|
212
|
+
s = s + value_block.call(element)
|
213
|
+
end
|
214
|
+
s
|
215
|
+
end
|
216
|
+
|
217
|
+
@as_sort_dirty = true
|
218
|
+
@as_last_comparison_block = nil
|
219
|
+
|
220
|
+
alias old_sort! sort!
|
221
|
+
# Adds smarter sorting: A lot of methods above need the array sorted and they may call one another. This sort! method only sorts the
|
222
|
+
# array if it isn't currently known to be sorted.
|
223
|
+
#
|
224
|
+
# Like most methods in this package, this method takes an optional block that defines the "value" of the objects in the array.
|
225
|
+
# This block can be safely skipped if the array contains numbers.
|
226
|
+
def sort!(&comparison_block) # :yields: element
|
227
|
+
if(dirty? || (comparison_block != @as_last_comparison_block))
|
228
|
+
old_sort!(&comparison_block)
|
229
|
+
@as_last_comparison_block = comparison_block
|
230
|
+
clean
|
231
|
+
end
|
232
|
+
self
|
233
|
+
end
|
234
|
+
|
235
|
+
#:stopdoc:
|
236
|
+
def dirty
|
237
|
+
@as_sort_dirty = true
|
238
|
+
end
|
239
|
+
|
240
|
+
def dirty?
|
241
|
+
dirty unless instance_variable_defined? :@as_sort_dirty
|
242
|
+
@as_sort_dirty
|
243
|
+
end
|
244
|
+
|
245
|
+
def clean
|
246
|
+
@as_sort_dirty = false
|
247
|
+
end
|
248
|
+
|
249
|
+
# BELOW: Modify the array to mark itself as dirty when the array might need resorting.
|
250
|
+
|
251
|
+
# For our purposes "Dirty" doesn't merely mean that the array has been modified, It means
|
252
|
+
# that the array has been modified in a way that could have messed up the sorting.
|
253
|
+
# For this reason, not all methods that could modify the array are included. e.g. anything
|
254
|
+
# that *JUST* removes elements doesn't mess up the order of the array, but insertions might.
|
255
|
+
|
256
|
+
# Side-note: there are a lot of array methods that don't follow the destructive-methods-end-in-! naming pattern
|
257
|
+
|
258
|
+
alias as_old_ass []=
|
259
|
+
def []=(*as_args)
|
260
|
+
ret = as_old_ass(*as_args)
|
261
|
+
dirty
|
262
|
+
ret
|
263
|
+
end
|
264
|
+
|
265
|
+
alias as_old_app <<
|
266
|
+
def <<(*as_args)
|
267
|
+
ret = as_old_app(*as_args)
|
268
|
+
dirty
|
269
|
+
ret
|
270
|
+
end
|
271
|
+
|
272
|
+
alias as_old_push push
|
273
|
+
def push(*as_args)
|
274
|
+
ret = as_old_push(*as_args)
|
275
|
+
dirty
|
276
|
+
ret
|
277
|
+
end
|
278
|
+
|
279
|
+
alias as_old_collect collect!
|
280
|
+
def collect!(*as_args, &block)
|
281
|
+
ret = as_old_collect(*as_args, &block)
|
282
|
+
dirty
|
283
|
+
ret
|
284
|
+
end
|
285
|
+
|
286
|
+
alias as_old_map! map!
|
287
|
+
def map!(*as_args, &block)
|
288
|
+
ret = as_old_map!(*as_args, &block)
|
289
|
+
dirty
|
290
|
+
ret
|
291
|
+
end
|
292
|
+
|
293
|
+
alias as_old_fill fill
|
294
|
+
def fill(*as_args, &block)
|
295
|
+
ret = as_old_fill(*as_args, &block)
|
296
|
+
dirty
|
297
|
+
ret
|
298
|
+
end
|
299
|
+
|
300
|
+
alias as_old_flatten flatten!
|
301
|
+
def flatten!(*as_args, &block)
|
302
|
+
ret = as_old_flatten(*as_args, &block)
|
303
|
+
dirty
|
304
|
+
ret
|
305
|
+
end
|
306
|
+
|
307
|
+
alias as_old_replace replace
|
308
|
+
def replace(*as_args, &block)
|
309
|
+
ret = as_old_replace(*as_args, &block)
|
310
|
+
dirty
|
311
|
+
ret
|
312
|
+
end
|
313
|
+
|
314
|
+
alias as_old_reverse reverse!
|
315
|
+
def reverse!(*as_args, &block)
|
316
|
+
ret = as_old_reverse(*as_args, &block)
|
317
|
+
dirty
|
318
|
+
ret
|
319
|
+
end
|
320
|
+
|
321
|
+
alias as_old_unshift unshift
|
322
|
+
def unshift(*as_args, &block)
|
323
|
+
ret = as_old_unshift(*as_args, &block)
|
324
|
+
dirty
|
325
|
+
ret
|
326
|
+
end
|
327
|
+
#:startdoc:
|
328
|
+
end
|
329
|
+
|
330
|
+
|
331
|
+
|
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/array_statistics.rb'}"
|
9
|
+
puts "Loading array_statistics gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
data/script/txt2html
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
load File.dirname(__FILE__) + "/../Rakefile"
|
4
|
+
require 'rubyforge'
|
5
|
+
require 'redcloth'
|
6
|
+
require 'syntax/convertors/html'
|
7
|
+
require 'erb'
|
8
|
+
|
9
|
+
download = "http://rubyforge.org/projects/#{$hoe.rubyforge_name}"
|
10
|
+
version = $hoe.version
|
11
|
+
|
12
|
+
def rubyforge_project_id
|
13
|
+
RubyForge.new.configure.autoconfig["group_ids"][$hoe.rubyforge_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
class Fixnum
|
17
|
+
def ordinal
|
18
|
+
# teens
|
19
|
+
return 'th' if (10..19).include?(self % 100)
|
20
|
+
# others
|
21
|
+
case self % 10
|
22
|
+
when 1: return 'st'
|
23
|
+
when 2: return 'nd'
|
24
|
+
when 3: return 'rd'
|
25
|
+
else return 'th'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Time
|
31
|
+
def pretty
|
32
|
+
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def convert_syntax(syntax, source)
|
37
|
+
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
38
|
+
end
|
39
|
+
|
40
|
+
if ARGV.length >= 1
|
41
|
+
src, template = ARGV
|
42
|
+
template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
|
43
|
+
else
|
44
|
+
puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
|
45
|
+
exit!
|
46
|
+
end
|
47
|
+
|
48
|
+
template = ERB.new(File.open(template).read)
|
49
|
+
|
50
|
+
title = nil
|
51
|
+
body = nil
|
52
|
+
File.open(src) do |fsrc|
|
53
|
+
title_text = fsrc.readline
|
54
|
+
body_text_template = fsrc.read
|
55
|
+
body_text = ERB.new(body_text_template).result(binding)
|
56
|
+
syntax_items = []
|
57
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
|
58
|
+
ident = syntax_items.length
|
59
|
+
element, syntax, source = $1, $2, $3
|
60
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
61
|
+
"syntax-temp-#{ident}"
|
62
|
+
}
|
63
|
+
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
64
|
+
body = RedCloth.new(body_text).to_html
|
65
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
66
|
+
end
|
67
|
+
stat = File.stat(src)
|
68
|
+
created = stat.ctime
|
69
|
+
modified = stat.mtime
|
70
|
+
|
71
|
+
$stdout << template.result(binding)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class TestArrayStatistics < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_empty_array
|
9
|
+
assert_same(0, [].median)
|
10
|
+
assert_same(0, [].median_indices)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_percentile
|
14
|
+
assert_nil([].percentile(1))
|
15
|
+
#edge cases
|
16
|
+
assert_nil([1,2,3,4,5,6,8].percentile(0))
|
17
|
+
assert_equal(8, [1,2,3,4,5,6,8].percentile(1))
|
18
|
+
assert_equal([1,2,3,4,5,6,8].percentile(135484), [1,2,3,4,5,6,8].percentile(1))
|
19
|
+
assert_equal([1,2,3,4,5,6,8].percentile(-3), [1,2,3,4,5,6,8].percentile(0))
|
20
|
+
#proper handling of midrange values
|
21
|
+
assert_equal(1, [1,2,3,4].percentile(0.0001))
|
22
|
+
assert_equal(1, [1,2,3,4].percentile(0.25))
|
23
|
+
assert_equal(1, [1,2,3,4].percentile(0.26))
|
24
|
+
assert_equal(2, [1,2,3,4].percentile(0.5))
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_percentile_rank
|
28
|
+
#edge cases
|
29
|
+
assert_equal(0, [1,2,3,4].percentile_rank(-1))
|
30
|
+
assert_equal(1, [1,2,3,4].percentile_rank(19849))
|
31
|
+
#proper handling of midrange values
|
32
|
+
assert_equal(0, [1,2,3,4].percentile_rank(0.99))
|
33
|
+
assert_equal(0.25, [1,2,3,4].percentile_rank(1))
|
34
|
+
assert_equal(0.25, [1,2,3,4].percentile_rank(1.3))
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_median
|
38
|
+
assert_equal(0, [].median)
|
39
|
+
assert_equal(666, [666].median)
|
40
|
+
assert_equal(1.5, [1,2].median)
|
41
|
+
assert_equal(3, [2,3,4].median)
|
42
|
+
assert_equal(2.5, [1,2,3,4].median)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_outliers
|
46
|
+
assert_equal([-60,999,9999], [-60,1,2,3,1,2,3,4,3,2,1,1,1,1,4,4,4,4,3,999, 9999].outliers)
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/test/test_helper.rb
ADDED
data/website/index.html
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
4
|
+
<title>array_statistics</title>
|
5
|
+
|
6
|
+
</head>
|
7
|
+
<body id="body">
|
8
|
+
<p>This page has not yet been created for RubyGem <code>array_statistics</code></p>
|
9
|
+
<p>To the developer: To generate it, update website/index.txt and run the rake task <code>website</code> to generate this <code>index.html</code> file.</p>
|
10
|
+
</body>
|
11
|
+
</html>
|
data/website/index.txt
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
h1. array_statistics
|
2
|
+
|
3
|
+
h1. → 'array_statistics'
|
4
|
+
|
5
|
+
|
6
|
+
h2. What
|
7
|
+
|
8
|
+
|
9
|
+
h2. Installing
|
10
|
+
|
11
|
+
<pre syntax="ruby">sudo gem install array_statistics</pre>
|
12
|
+
|
13
|
+
h2. The basics
|
14
|
+
|
15
|
+
|
16
|
+
h2. Demonstration of usage
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
h2. Forum
|
21
|
+
|
22
|
+
"http://groups.google.com/group/array_statistics":http://groups.google.com/group/array_statistics
|
23
|
+
|
24
|
+
TODO - create Google Group - array_statistics
|
25
|
+
|
26
|
+
h2. How to submit patches
|
27
|
+
|
28
|
+
Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above.
|
29
|
+
|
30
|
+
TODO - pick SVN or Git instructions
|
31
|
+
|
32
|
+
The trunk repository is <code>svn://rubyforge.org/var/svn/array_statistics/trunk</code> for anonymous access.
|
33
|
+
|
34
|
+
OOOORRRR
|
35
|
+
|
36
|
+
You can fetch the source from either:
|
37
|
+
|
38
|
+
<% if rubyforge_project_id %>
|
39
|
+
|
40
|
+
* rubyforge: "http://rubyforge.org/scm/?group_id=<%= rubyforge_project_id %>":http://rubyforge.org/scm/?group_id=<%= rubyforge_project_id %>
|
41
|
+
|
42
|
+
<pre>git clone git://rubyforge.org/array_statistics.git</pre>
|
43
|
+
|
44
|
+
<% else %>
|
45
|
+
|
46
|
+
* rubyforge: MISSING IN ACTION
|
47
|
+
|
48
|
+
TODO - You can not created a RubyForge project, OR have not run <code>rubyforge config</code>
|
49
|
+
yet to refresh your local rubyforge data with this projects' id information.
|
50
|
+
|
51
|
+
When you do this, this message will magically disappear!
|
52
|
+
|
53
|
+
Or you can hack website/index.txt and make it all go away!!
|
54
|
+
|
55
|
+
<% end %>
|
56
|
+
|
57
|
+
* github: "http://github.com/GITHUB_USERNAME/array_statistics/tree/master":http://github.com/GITHUB_USERNAME/array_statistics/tree/master
|
58
|
+
|
59
|
+
<pre>git clone git://github.com/GITHUB_USERNAME/array_statistics.git</pre>
|
60
|
+
|
61
|
+
|
62
|
+
TODO - add "github_username: username" to ~/.rubyforge/user-config.yml and newgem will reuse it for future projects.
|
63
|
+
|
64
|
+
|
65
|
+
* gitorious: "git://gitorious.org/array_statistics/mainline.git":git://gitorious.org/array_statistics/mainline.git
|
66
|
+
|
67
|
+
<pre>git clone git://gitorious.org/array_statistics/mainline.git</pre>
|
68
|
+
|
69
|
+
h3. Build and test instructions
|
70
|
+
|
71
|
+
<pre>cd array_statistics
|
72
|
+
rake test
|
73
|
+
rake install_gem</pre>
|
74
|
+
|
75
|
+
|
76
|
+
h2. License
|
77
|
+
|
78
|
+
This code is free to use under the terms of the MIT license.
|
79
|
+
|
80
|
+
h2. Contact
|
81
|
+
|
82
|
+
Comments are welcome. Send an email to "FIXME full name":mailto:FIXME email via the "forum":http://groups.google.com/group/array_statistics
|
83
|
+
|
@@ -0,0 +1,285 @@
|
|
1
|
+
|
2
|
+
/****************************************************************
|
3
|
+
* *
|
4
|
+
* curvyCorners *
|
5
|
+
* ------------ *
|
6
|
+
* *
|
7
|
+
* This script generates rounded corners for your divs. *
|
8
|
+
* *
|
9
|
+
* Version 1.2.9 *
|
10
|
+
* Copyright (c) 2006 Cameron Cooke *
|
11
|
+
* By: Cameron Cooke and Tim Hutchison. *
|
12
|
+
* *
|
13
|
+
* *
|
14
|
+
* Website: http://www.curvycorners.net *
|
15
|
+
* Email: info@totalinfinity.com *
|
16
|
+
* Forum: http://www.curvycorners.net/forum/ *
|
17
|
+
* *
|
18
|
+
* *
|
19
|
+
* This library is free software; you can redistribute *
|
20
|
+
* it and/or modify it under the terms of the GNU *
|
21
|
+
* Lesser General Public License as published by the *
|
22
|
+
* Free Software Foundation; either version 2.1 of the *
|
23
|
+
* License, or (at your option) any later version. *
|
24
|
+
* *
|
25
|
+
* This library is distributed in the hope that it will *
|
26
|
+
* be useful, but WITHOUT ANY WARRANTY; without even the *
|
27
|
+
* implied warranty of MERCHANTABILITY or FITNESS FOR A *
|
28
|
+
* PARTICULAR PURPOSE. See the GNU Lesser General Public *
|
29
|
+
* License for more details. *
|
30
|
+
* *
|
31
|
+
* You should have received a copy of the GNU Lesser *
|
32
|
+
* General Public License along with this library; *
|
33
|
+
* Inc., 59 Temple Place, Suite 330, Boston, *
|
34
|
+
* MA 02111-1307 USA *
|
35
|
+
* *
|
36
|
+
****************************************************************/
|
37
|
+
|
38
|
+
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
|
39
|
+
{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
|
40
|
+
{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
|
41
|
+
else
|
42
|
+
{ var startIndex = 1; var boxCol = arguments;}
|
43
|
+
var curvyCornersCol = new Array(); if(arguments[0].validTags)
|
44
|
+
var validElements = arguments[0].validTags; else
|
45
|
+
var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++)
|
46
|
+
{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false)
|
47
|
+
{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);}
|
48
|
+
}
|
49
|
+
this.objects = curvyCornersCol; this.applyCornersToAll = function()
|
50
|
+
{ for(var x = 0, k = this.objects.length; x < k; x++)
|
51
|
+
{ this.objects[x].applyCorners();}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
function curvyObject()
|
55
|
+
{ this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width"); var borderColour = get_style(this.box, "borderTopColor", "border-top-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingTop", "padding-top"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0)
|
56
|
+
this.box.innerHTML = ""; this.applyCorners = function()
|
57
|
+
{ for(var t = 0; t < 2; t++)
|
58
|
+
{ switch(t)
|
59
|
+
{ case 0:
|
60
|
+
if(this.settings.tl || this.settings.tr)
|
61
|
+
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);}
|
62
|
+
break; case 1:
|
63
|
+
if(this.settings.bl || this.settings.br)
|
64
|
+
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);}
|
65
|
+
break;}
|
66
|
+
}
|
67
|
+
if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners)
|
68
|
+
{ if(i > -1 < 4)
|
69
|
+
{ var cc = corners[i]; if(!this.settings[cc])
|
70
|
+
{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
|
71
|
+
{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "")
|
72
|
+
newCorner.style.backgroundColor = this.boxColour; else
|
73
|
+
newCorner.style.backgroundImage = this.backgroundImage; switch(cc)
|
74
|
+
{ case "tl":
|
75
|
+
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr":
|
76
|
+
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl":
|
77
|
+
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br":
|
78
|
+
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px"
|
79
|
+
newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
else
|
83
|
+
{ if(this.masterCorners[this.settings[cc].radius])
|
84
|
+
{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);}
|
85
|
+
else
|
86
|
+
{ var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++)
|
87
|
+
{ if((intx +1) >= borderRadius)
|
88
|
+
var y1 = -1; else
|
89
|
+
var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j)
|
90
|
+
{ if((intx) >= borderRadius)
|
91
|
+
var y2 = -1; else
|
92
|
+
var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j)
|
93
|
+
var y3 = -1; else
|
94
|
+
var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);}
|
95
|
+
if((intx) >= j)
|
96
|
+
var y4 = -1; else
|
97
|
+
var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j)
|
98
|
+
{ for(var inty = (y1 + 1); inty < y2; inty++)
|
99
|
+
{ if(this.settings.antiAlias)
|
100
|
+
{ if(this.backgroundImage != "")
|
101
|
+
{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30)
|
102
|
+
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);}
|
103
|
+
else
|
104
|
+
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);}
|
105
|
+
}
|
106
|
+
else
|
107
|
+
{ var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
if(this.settings.antiAlias)
|
111
|
+
{ if(y3 >= y2)
|
112
|
+
{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);}
|
113
|
+
}
|
114
|
+
else
|
115
|
+
{ if(y3 >= y1)
|
116
|
+
{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);}
|
117
|
+
}
|
118
|
+
var outsideColour = this.borderColour;}
|
119
|
+
else
|
120
|
+
{ var outsideColour = this.boxColour; var y3 = y1;}
|
121
|
+
if(this.settings.antiAlias)
|
122
|
+
{ for(var inty = (y3 + 1); inty < y4; inty++)
|
123
|
+
{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);}
|
127
|
+
if(cc != "br")
|
128
|
+
{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
|
129
|
+
{ var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";}
|
130
|
+
if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";}
|
131
|
+
switch(cc)
|
132
|
+
{ case "tr":
|
133
|
+
pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl":
|
134
|
+
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl":
|
135
|
+
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
if(newCorner)
|
140
|
+
{ switch(cc)
|
141
|
+
{ case "tl":
|
142
|
+
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr":
|
143
|
+
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl":
|
144
|
+
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br":
|
145
|
+
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
|
150
|
+
radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff)
|
151
|
+
{ if(z == "t" || z == "b")
|
152
|
+
{ if(radiusDiff[z])
|
153
|
+
{ var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px"
|
154
|
+
newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType)
|
155
|
+
{ case "tl":
|
156
|
+
newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr":
|
157
|
+
newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl":
|
158
|
+
newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br":
|
159
|
+
newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;}
|
160
|
+
}
|
161
|
+
var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z)
|
162
|
+
{ case "t":
|
163
|
+
if(this.topContainer)
|
164
|
+
{ if(this.settings.tl.radius && this.settings.tr.radius)
|
165
|
+
{ newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "")
|
166
|
+
newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);}
|
167
|
+
this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";}
|
168
|
+
break; case "b":
|
169
|
+
if(this.bottomContainer)
|
170
|
+
{ if(this.settings.bl.radius && this.settings.br.radius)
|
171
|
+
{ newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "")
|
172
|
+
newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);}
|
173
|
+
}
|
174
|
+
break;}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
if(this.settings.autoPad == true && this.boxPadding > 0)
|
178
|
+
{ var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding)
|
179
|
+
contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding)
|
180
|
+
contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);}
|
181
|
+
}
|
182
|
+
this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
|
183
|
+
{ var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "")
|
184
|
+
{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";}
|
185
|
+
else
|
186
|
+
{ pixel.style.backgroundColor = colour;}
|
187
|
+
if (transAmount != 100)
|
188
|
+
setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);}
|
189
|
+
}
|
190
|
+
function insertAfter(parent, node, referenceNode)
|
191
|
+
{ parent.insertBefore(node, referenceNode.nextSibling);}
|
192
|
+
function BlendColour(Col1, Col2, Col1Fraction)
|
193
|
+
{ var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);}
|
194
|
+
function IntToHex(strNum)
|
195
|
+
{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;}
|
196
|
+
function MakeHex(x)
|
197
|
+
{ if((x >= 0) && (x <= 9))
|
198
|
+
{ return x;}
|
199
|
+
else
|
200
|
+
{ switch(x)
|
201
|
+
{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
function pixelFraction(x, y, r)
|
205
|
+
{ var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1)))
|
206
|
+
{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;}
|
207
|
+
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1)))
|
208
|
+
{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;}
|
209
|
+
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1)))
|
210
|
+
{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;}
|
211
|
+
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1)))
|
212
|
+
{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;}
|
213
|
+
switch (whatsides)
|
214
|
+
{ case "LeftRight":
|
215
|
+
pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight":
|
216
|
+
pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom":
|
217
|
+
pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom":
|
218
|
+
pixelfraction = (yvalues[0]*xvalues[1])/2; break; default:
|
219
|
+
pixelfraction = 1;}
|
220
|
+
return pixelfraction;}
|
221
|
+
function rgb2Hex(rgbColour)
|
222
|
+
{ try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);}
|
223
|
+
catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");}
|
224
|
+
return hexColour;}
|
225
|
+
function rgb2Array(rgbColour)
|
226
|
+
{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;}
|
227
|
+
function setOpacity(obj, opacity)
|
228
|
+
{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME")
|
229
|
+
{ var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";}
|
230
|
+
else if(typeof(obj.style.opacity) != "undefined")
|
231
|
+
{ obj.style.opacity = opacity/100;}
|
232
|
+
else if(typeof(obj.style.MozOpacity) != "undefined")
|
233
|
+
{ obj.style.MozOpacity = opacity/100;}
|
234
|
+
else if(typeof(obj.style.filter) != "undefined")
|
235
|
+
{ obj.style.filter = "alpha(opacity:" + opacity + ")";}
|
236
|
+
else if(typeof(obj.style.KHTMLOpacity) != "undefined")
|
237
|
+
{ obj.style.KHTMLOpacity = opacity/100;}
|
238
|
+
}
|
239
|
+
function inArray(array, value)
|
240
|
+
{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;}
|
241
|
+
return false;}
|
242
|
+
function inArrayKey(array, value)
|
243
|
+
{ for(key in array){ if(key === value) return true;}
|
244
|
+
return false;}
|
245
|
+
function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;}
|
246
|
+
else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;}
|
247
|
+
else { elm['on' + evType] = fn;}
|
248
|
+
}
|
249
|
+
function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");}
|
250
|
+
}
|
251
|
+
function format_colour(colour)
|
252
|
+
{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent")
|
253
|
+
{ if(colour.substr(0, 3) == "rgb")
|
254
|
+
{ returnColour = rgb2Hex(colour);}
|
255
|
+
else if(colour.length == 4)
|
256
|
+
{ returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);}
|
257
|
+
else
|
258
|
+
{ returnColour = colour;}
|
259
|
+
}
|
260
|
+
return returnColour;}
|
261
|
+
function get_style(obj, property, propertyNS)
|
262
|
+
{ try
|
263
|
+
{ if(obj.currentStyle)
|
264
|
+
{ var returnVal = eval("obj.currentStyle." + property);}
|
265
|
+
else
|
266
|
+
{ if(isSafari && obj.style.display == "none")
|
267
|
+
{ obj.style.display = ""; var wasHidden = true;}
|
268
|
+
var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden)
|
269
|
+
{ obj.style.display = "none";}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
catch(e)
|
273
|
+
{ }
|
274
|
+
return returnVal;}
|
275
|
+
function getElementsByClass(searchClass, node, tag)
|
276
|
+
{ var classElements = new Array(); if(node == null)
|
277
|
+
node = document; if(tag == null)
|
278
|
+
tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++)
|
279
|
+
{ if(pattern.test(els[i].className))
|
280
|
+
{ classElements[j] = els[i]; j++;}
|
281
|
+
}
|
282
|
+
return classElements;}
|
283
|
+
function newCurvyError(errorMessage)
|
284
|
+
{ return new Error("curvyCorners Error:\n" + errorMessage)
|
285
|
+
}
|
@@ -0,0 +1,138 @@
|
|
1
|
+
body {
|
2
|
+
background-color: #E1D1F1;
|
3
|
+
font-family: "Georgia", sans-serif;
|
4
|
+
font-size: 16px;
|
5
|
+
line-height: 1.6em;
|
6
|
+
padding: 1.6em 0 0 0;
|
7
|
+
color: #333;
|
8
|
+
}
|
9
|
+
h1, h2, h3, h4, h5, h6 {
|
10
|
+
color: #444;
|
11
|
+
}
|
12
|
+
h1 {
|
13
|
+
font-family: sans-serif;
|
14
|
+
font-weight: normal;
|
15
|
+
font-size: 4em;
|
16
|
+
line-height: 0.8em;
|
17
|
+
letter-spacing: -0.1ex;
|
18
|
+
margin: 5px;
|
19
|
+
}
|
20
|
+
li {
|
21
|
+
padding: 0;
|
22
|
+
margin: 0;
|
23
|
+
list-style-type: square;
|
24
|
+
}
|
25
|
+
a {
|
26
|
+
color: #5E5AFF;
|
27
|
+
background-color: #DAC;
|
28
|
+
font-weight: normal;
|
29
|
+
text-decoration: underline;
|
30
|
+
}
|
31
|
+
blockquote {
|
32
|
+
font-size: 90%;
|
33
|
+
font-style: italic;
|
34
|
+
border-left: 1px solid #111;
|
35
|
+
padding-left: 1em;
|
36
|
+
}
|
37
|
+
.caps {
|
38
|
+
font-size: 80%;
|
39
|
+
}
|
40
|
+
|
41
|
+
#main {
|
42
|
+
width: 45em;
|
43
|
+
padding: 0;
|
44
|
+
margin: 0 auto;
|
45
|
+
}
|
46
|
+
.coda {
|
47
|
+
text-align: right;
|
48
|
+
color: #77f;
|
49
|
+
font-size: smaller;
|
50
|
+
}
|
51
|
+
|
52
|
+
table {
|
53
|
+
font-size: 90%;
|
54
|
+
line-height: 1.4em;
|
55
|
+
color: #ff8;
|
56
|
+
background-color: #111;
|
57
|
+
padding: 2px 10px 2px 10px;
|
58
|
+
border-style: dashed;
|
59
|
+
}
|
60
|
+
|
61
|
+
th {
|
62
|
+
color: #fff;
|
63
|
+
}
|
64
|
+
|
65
|
+
td {
|
66
|
+
padding: 2px 10px 2px 10px;
|
67
|
+
}
|
68
|
+
|
69
|
+
.success {
|
70
|
+
color: #0CC52B;
|
71
|
+
}
|
72
|
+
|
73
|
+
.failed {
|
74
|
+
color: #E90A1B;
|
75
|
+
}
|
76
|
+
|
77
|
+
.unknown {
|
78
|
+
color: #995000;
|
79
|
+
}
|
80
|
+
pre, code {
|
81
|
+
font-family: monospace;
|
82
|
+
font-size: 90%;
|
83
|
+
line-height: 1.4em;
|
84
|
+
color: #ff8;
|
85
|
+
background-color: #111;
|
86
|
+
padding: 2px 10px 2px 10px;
|
87
|
+
}
|
88
|
+
.comment { color: #aaa; font-style: italic; }
|
89
|
+
.keyword { color: #eff; font-weight: bold; }
|
90
|
+
.punct { color: #eee; font-weight: bold; }
|
91
|
+
.symbol { color: #0bb; }
|
92
|
+
.string { color: #6b4; }
|
93
|
+
.ident { color: #ff8; }
|
94
|
+
.constant { color: #66f; }
|
95
|
+
.regex { color: #ec6; }
|
96
|
+
.number { color: #F99; }
|
97
|
+
.expr { color: #227; }
|
98
|
+
|
99
|
+
#version {
|
100
|
+
float: right;
|
101
|
+
text-align: right;
|
102
|
+
font-family: sans-serif;
|
103
|
+
font-weight: normal;
|
104
|
+
background-color: #B3ABFF;
|
105
|
+
color: #141331;
|
106
|
+
padding: 15px 20px 10px 20px;
|
107
|
+
margin: 0 auto;
|
108
|
+
margin-top: 15px;
|
109
|
+
border: 3px solid #141331;
|
110
|
+
}
|
111
|
+
|
112
|
+
#version .numbers {
|
113
|
+
display: block;
|
114
|
+
font-size: 4em;
|
115
|
+
line-height: 0.8em;
|
116
|
+
letter-spacing: -0.1ex;
|
117
|
+
margin-bottom: 15px;
|
118
|
+
}
|
119
|
+
|
120
|
+
#version p {
|
121
|
+
text-decoration: none;
|
122
|
+
color: #141331;
|
123
|
+
background-color: #B3ABFF;
|
124
|
+
margin: 0;
|
125
|
+
padding: 0;
|
126
|
+
}
|
127
|
+
|
128
|
+
#version a {
|
129
|
+
text-decoration: none;
|
130
|
+
color: #141331;
|
131
|
+
background-color: #B3ABFF;
|
132
|
+
}
|
133
|
+
|
134
|
+
.clickable {
|
135
|
+
cursor: pointer;
|
136
|
+
cursor: hand;
|
137
|
+
}
|
138
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
|
+
<title>
|
8
|
+
<%= title %>
|
9
|
+
</title>
|
10
|
+
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
11
|
+
<style>
|
12
|
+
|
13
|
+
</style>
|
14
|
+
<script type="text/javascript">
|
15
|
+
window.onload = function() {
|
16
|
+
settings = {
|
17
|
+
tl: { radius: 10 },
|
18
|
+
tr: { radius: 10 },
|
19
|
+
bl: { radius: 10 },
|
20
|
+
br: { radius: 10 },
|
21
|
+
antiAlias: true,
|
22
|
+
autoPad: true,
|
23
|
+
validTags: ["div"]
|
24
|
+
}
|
25
|
+
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
26
|
+
versionBox.applyCornersToAll();
|
27
|
+
}
|
28
|
+
</script>
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="main">
|
32
|
+
|
33
|
+
<h1><%= title %></h1>
|
34
|
+
<div id="version" class="clickable" onclick='document.location = "<%= download %>"; return false'>
|
35
|
+
<p>Get Version</p>
|
36
|
+
<a href="<%= download %>" class="numbers"><%= version %></a>
|
37
|
+
</div>
|
38
|
+
<%= body %>
|
39
|
+
<p class="coda">
|
40
|
+
<a href="FIXME email">FIXME full name</a>, <%= modified.pretty %><br>
|
41
|
+
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
42
|
+
</p>
|
43
|
+
</div>
|
44
|
+
|
45
|
+
<!-- insert site tracking codes here, like Google Urchin -->
|
46
|
+
|
47
|
+
</body>
|
48
|
+
</html>
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: array_statistics
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bruce Goodwin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-10-30 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: newgem
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.0.1
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.8.2
|
34
|
+
version:
|
35
|
+
description: Array Statistics adds statistical operations to the ruby Array class.
|
36
|
+
email:
|
37
|
+
- rubybg@gmail.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files:
|
43
|
+
- History.txt
|
44
|
+
- Manifest.txt
|
45
|
+
- PostInstall.txt
|
46
|
+
- website/index.txt
|
47
|
+
files:
|
48
|
+
- History.txt
|
49
|
+
- Manifest.txt
|
50
|
+
- PostInstall.txt
|
51
|
+
- README.rdoc
|
52
|
+
- Rakefile
|
53
|
+
- config/website.yml.sample
|
54
|
+
- lib/array_statistics.rb
|
55
|
+
- script/console
|
56
|
+
- script/destroy
|
57
|
+
- script/generate
|
58
|
+
- script/txt2html
|
59
|
+
- test/test_array_statistics.rb
|
60
|
+
- test/test_helper.rb
|
61
|
+
- website/index.html
|
62
|
+
- website/index.txt
|
63
|
+
- website/javascripts/rounded_corners_lite.inc.js
|
64
|
+
- website/stylesheets/screen.css
|
65
|
+
- website/template.html.erb
|
66
|
+
has_rdoc: true
|
67
|
+
homepage: http://rubyforge.org/projects/array-statistic/
|
68
|
+
post_install_message: PostInstall.txt
|
69
|
+
rdoc_options:
|
70
|
+
- --main
|
71
|
+
- README.rdoc
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: "0"
|
85
|
+
version:
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: array_statistics
|
89
|
+
rubygems_version: 1.3.1
|
90
|
+
signing_key:
|
91
|
+
specification_version: 2
|
92
|
+
summary: Array Statistics adds statistical operations to the ruby Array class.
|
93
|
+
test_files:
|
94
|
+
- test/test_array_statistics.rb
|
95
|
+
- test/test_helper.rb
|