cotcube-helpers 0.1.4 → 0.1.7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/VERSION +1 -1
- data/lib/cotcube-helpers.rb +1 -0
- data/lib/cotcube-helpers/array_ext.rb +41 -0
- data/lib/cotcube-helpers/datetime_ext.rb +12 -0
- data/lib/cotcube-helpers/parallelize.rb +3 -3
- data/lib/cotcube-helpers/range_ext.rb +56 -49
- data/lib/cotcube-helpers/simple_series_stats.rb +54 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91263c1bbd453c5b1e6c8a3cfe7c0dee3542f5873e82d15caf8118b6b20ce603
|
4
|
+
data.tar.gz: f886c9fe330f439b61c0aee1f3c9cc55b3df161511968c25bb92df5cb85c2f0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '00591395a0289380b4063ffa6766073d7619d1f7cc0576afb722854cbdc97f03d5bd651feaaf6a5f49de61770f6d16982a3ae7de26a9fd030c40efec6198e9f5'
|
7
|
+
data.tar.gz: c25f08c4677106ec7dc714653830bb6f9ef668f70df50343c443f0d0c79dccd110bf425fe7fa8cdc28b7ecf18db2d3aafd7cccd5f00b2bb5f3a8113fc17f65fa
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
## 0.1.7 (January 17, 2021)
|
2
|
+
- added new method 'simple_series_stats'
|
3
|
+
|
4
|
+
## 0.1.6 (January 15, 2021)
|
5
|
+
- removing :ranges from Range#select_within
|
6
|
+
- Added Array#select_right_by
|
7
|
+
|
8
|
+
## 0.1.5.4 (January 02, 2021)
|
9
|
+
|
10
|
+
|
11
|
+
## 1.5.1.3 (January 02, 2021)
|
12
|
+
- hotfixing the hotfix (hello CI tools, c ya coming)
|
13
|
+
|
14
|
+
## 1.5.1.2 (January 02, 2021)
|
15
|
+
- hotfix problem in Range.to_time_intervals
|
16
|
+
|
17
|
+
## 0.1.5.1 (January 02, 2021)
|
18
|
+
- Hotfixing parallelize
|
19
|
+
|
20
|
+
## 0.1.5 (January 02, 2021)
|
21
|
+
- applied new datetime helper to Range#to_time_intervals
|
22
|
+
- added new DateTime extension, containing 'to_seconds_since_sunday_morning'
|
23
|
+
- added #select_within to array_ext
|
24
|
+
|
1
25
|
## 0.1.4 (December 27, 2020)
|
2
26
|
- applied cops
|
3
27
|
- added README for reduce; minor changes
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.7
|
data/lib/cotcube-helpers.rb
CHANGED
@@ -12,6 +12,7 @@ require_relative 'cotcube-helpers/enum_ext'
|
|
12
12
|
require_relative 'cotcube-helpers/hash_ext'
|
13
13
|
require_relative 'cotcube-helpers/range_ext'
|
14
14
|
require_relative 'cotcube-helpers/string_ext'
|
15
|
+
require_relative 'cotcube-helpers/datetime_ext'
|
15
16
|
require_relative 'cotcube-helpers/subpattern'
|
16
17
|
require_relative 'cotcube-helpers/parallelize'
|
17
18
|
require_relative 'cotcube-helpers/simple_output'
|
@@ -53,4 +53,45 @@ class Array
|
|
53
53
|
block.call(self[i - 2], self[i - 1], self[i])
|
54
54
|
end.compact
|
55
55
|
end
|
56
|
+
|
57
|
+
# selects all elements from array that fit in given ranges.
|
58
|
+
# if :attr is given, selects all elements, where elem[:attr] fit
|
59
|
+
# raises if elem.first[attr].nil?
|
60
|
+
def select_within(ranges:, attr: nil, &block)
|
61
|
+
unless attr.nil? || first[attr]
|
62
|
+
raise ArgumentError,
|
63
|
+
"At least first element of Array '#{first}' does not contain attr '#{attr}'!"
|
64
|
+
end
|
65
|
+
raise ArgumentError, 'Ranges should be an Array or, more precisely, respond_to :map' unless ranges.respond_to? :map
|
66
|
+
raise ArgumentError, 'Each range in :ranges should respond to .include!' unless ranges.map do |x|
|
67
|
+
x.respond_to? :include?
|
68
|
+
end.reduce(:&)
|
69
|
+
|
70
|
+
select do |el|
|
71
|
+
value = attr.nil? ? el : el[attr]
|
72
|
+
ranges.map do |range|
|
73
|
+
range.include?(block.nil? ? value : block.call(value))
|
74
|
+
end.reduce(:|)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def select_right_by(inclusive: false, exclusive: false, initial: [], &block)
|
79
|
+
# unless range.is_a? Range and
|
80
|
+
# (range.begin.nil? or range.begin.is_a?(Integer)) and
|
81
|
+
# (range.end.nil? or range.end.is_a?(Integer))
|
82
|
+
# raise ArgumentError, ":range, if given, must be a range of ( nil|Integer..nil|Integer), got '#{range}'"
|
83
|
+
# end
|
84
|
+
|
85
|
+
raise ArgumentError, 'No block given.' unless block.is_a? Proc
|
86
|
+
|
87
|
+
inclusive = true unless exclusive
|
88
|
+
if inclusive && exclusive
|
89
|
+
raise ArgumentError,
|
90
|
+
"Either :inclusive or :exclusive must remain falsey, got '#{inclusive}' and '#{exclusive}'"
|
91
|
+
end
|
92
|
+
|
93
|
+
index = find_index { |obj| block.call(obj) }
|
94
|
+
|
95
|
+
self[((inclusive ? index : index + 1)..)]
|
96
|
+
end
|
56
97
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Monkey patching the Ruby class DateTime
|
4
|
+
class DateTime
|
5
|
+
# based on the fact that sunday is 'wday 0' plus that trading week starts
|
6
|
+
# sunday 0:00 (as trading starts sunday 5pm CT to fit tokyo monday morning)
|
7
|
+
def to_seconds_since_sunday_morning
|
8
|
+
wday * 86_400 + hour * 3600 + min * 60 + sec
|
9
|
+
end
|
10
|
+
|
11
|
+
alias to_sssm to_seconds_since_sunday_morning
|
12
|
+
end
|
@@ -7,9 +7,9 @@ module Cotcube
|
|
7
7
|
def parallelize(ary, processes: 1, threads: 1, progress: '', &block)
|
8
8
|
chunks = []
|
9
9
|
if [0, 1].include? processes
|
10
|
-
result = Parallel.map(ary, in_threads: threads
|
11
|
-
elsif [0, 1].include?
|
12
|
-
result = Parallel.map(ary, in_processes: processes
|
10
|
+
result = Parallel.map(ary, in_threads: threads, &block)
|
11
|
+
elsif [0, 1].include? threads
|
12
|
+
result = Parallel.map(ary, in_processes: processes, &block)
|
13
13
|
else
|
14
14
|
ary.each_slice(threads) { |chunk| chunks << chunk }
|
15
15
|
result = if progress == ''
|
@@ -2,11 +2,17 @@
|
|
2
2
|
|
3
3
|
# Monkey patching the Ruby Core class Range
|
4
4
|
class Range
|
5
|
-
def to_time_intervals(step:,
|
5
|
+
def to_time_intervals(step:,
|
6
|
+
timezone: Time.find_zone('America/Chicago'),
|
7
|
+
# ranges: nil,
|
8
|
+
debug: false)
|
6
9
|
unless step.is_a? ActiveSupport::Duration
|
7
10
|
raise ArgumentError,
|
8
11
|
":step must be a 'ActiveSupport::Duration', like '15.minutes', but '#{step}' is a '#{step.class}'"
|
9
12
|
end
|
13
|
+
unless [15.minutes, 60.minutes, 1.hour, 1.day].include? step
|
14
|
+
raise ArgumentError, 'Sorry, currently supporting only 15.minutes, 1.hour, 1.day as :step'
|
15
|
+
end
|
10
16
|
|
11
17
|
valid_classes = [ActiveSupport::TimeWithZone, Time, Date, DateTime]
|
12
18
|
unless timezone.is_a? ActiveSupport::TimeZone
|
@@ -26,64 +32,65 @@ class Range
|
|
26
32
|
":self.end seems not to be proper time value: #{ending} is a #{ending.class}"
|
27
33
|
end
|
28
34
|
|
29
|
-
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
35
|
+
# here sub-day and super-day need to be distinguished, as they react differently to daylight time
|
36
|
+
# for super-day, just return an array containing all calendar days
|
37
|
+
if step.to_i >= 1.day
|
38
|
+
(starting.to_date..ending.to_date).to_a.map(&:to_datetime)
|
39
|
+
else
|
34
40
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
(not ranges.nil?) && ranges.empty? ? true : (not [6, 0].include?(x.wday))
|
42
|
-
end
|
43
|
-
end
|
41
|
+
# sub-day is checked for DST
|
42
|
+
# noinspection RubyNilAnalysis
|
43
|
+
actual_starting = starting.to_time.to_i
|
44
|
+
actual_ending = ending.to_time.to_i
|
45
|
+
actual_ending -= 3600 if starting.dst? && (not ending.dst?)
|
46
|
+
actual_ending += 3600 if ending.dst? && (not starting.dst?)
|
44
47
|
|
45
|
-
|
46
|
-
|
48
|
+
##### The following is the actual big magic line, as it creates the raw target array:
|
49
|
+
#
|
50
|
+
result = (actual_starting..actual_ending).step(step).to_a.map { |x| timezone.at(x) }
|
51
|
+
#
|
52
|
+
# ###################<3##
|
47
53
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
regex = /^(?<hour>\d+):(?<minute>\d+)(?<morning>[pa]).?m.*/
|
54
|
+
# It should probably relocated to Cotcube::Bardata
|
55
|
+
# NOTE: In this current version 12 belongs to it succeeding hour
|
56
|
+
# i.e. 12am is right before 1am and 12pm right before 1pm
|
57
|
+
convert_to_sec_since = lambda do |clocking|
|
58
|
+
from_src, to_src = clocking.split(' - ')
|
59
|
+
regex = /^(?<hour>\d+):(?<minute>\d+)(?<morning>[pa]).?m.*/
|
55
60
|
|
56
|
-
|
57
|
-
|
61
|
+
from = from_src.match(regex)
|
62
|
+
to = to_src.match(regex)
|
58
63
|
|
59
|
-
|
60
|
-
|
64
|
+
from_i = from[:hour].to_i * 3600 + from[:minute].to_i * 60 + (from[:morning] == 'a' ? 2 : 1) * 12 * 3600
|
65
|
+
to_i = to[:hour].to_i * 3600 + to[:minute].to_i * 60 + (to[:morning] == 'a' ? 2 : 3) * 12 * 3600
|
61
66
|
|
62
|
-
|
63
|
-
|
64
|
-
|
67
|
+
(0...5).to_a.map { |i| [from_i + i * 24 * 3600, to_i + i * 24 * 3600] }
|
68
|
+
end
|
69
|
+
convert_to_sec_since.call('9:00a.m - 5:00p.m.')
|
65
70
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
]
|
71
|
+
# ranges ||= [
|
72
|
+
# 61_200...144_000, # Sun 5pm .. Mon 4pm
|
73
|
+
# 147_600...230_400, # Mon 5pm .. Tue 4pm
|
74
|
+
# 234_000...316_800, # ...
|
75
|
+
# 320_400...403_200,
|
76
|
+
# 406_800...489_600
|
77
|
+
# ]
|
74
78
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
79
|
+
# if there was a change towards daylight saving time, subtract 1 hour, otherwise add 1 hour
|
80
|
+
result.map! do |time|
|
81
|
+
print "#{time}\t" if debug
|
82
|
+
if (not starting.dst?) && time.dst?
|
83
|
+
time -= 3600
|
84
|
+
print "Time reduced (not starting_DST, but current\t" if debug
|
85
|
+
elsif starting.dst? && (not time.dst?)
|
86
|
+
time += 3600
|
87
|
+
print "Time extended (starting DST, but not current\t" if debug
|
88
|
+
end
|
89
|
+
puts "#{time} " if debug
|
82
90
|
time
|
83
91
|
end
|
84
|
-
end
|
85
|
-
return result if ranges.empty?
|
86
92
|
|
87
|
-
|
93
|
+
result # .select_within(ranges: ranges) { |x| x.to_datetime.to_seconds_since_sunday_morning }
|
94
|
+
end
|
88
95
|
end
|
89
96
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cotcube
|
4
|
+
# Missing top level documentation
|
5
|
+
module Helpers
|
6
|
+
# if given a block, :ind of base is set by block.call()
|
7
|
+
# dim reduces the sample size by top n% and least n%, so dim of 0.5 would remove 100% of the sample
|
8
|
+
def simple_series_stats(base:, ind: nil, dim: 0, format: '%5.2f', print: true, &block)
|
9
|
+
raise ArgumentError, 'Need :ind of type integer' if base.first.is_a?(Array) and not ind.is_a?(Integer)
|
10
|
+
raise ArgumentError, 'Need :ind to evaluate base' if base.first.is_a?(Hash) and ind.nil?
|
11
|
+
|
12
|
+
dim = dim.to_f if dim.is_a? Numeric
|
13
|
+
dim = 0 if dim==false
|
14
|
+
|
15
|
+
raise ArgumentError, 'Expecting 0 <= :dim < 0.5' unless dim.is_a?(Float) and dim >= 0 and dim < 0.5
|
16
|
+
raise ArgumentError, 'Expecting arity of one if block given' if block_given? and not block.arity==1
|
17
|
+
|
18
|
+
precision = format[-1] == 'f' ? format[..-2].split('.').last.to_i : 0
|
19
|
+
worker = base.
|
20
|
+
tap {|b| b.map{|x| x[ind] = block.call(x) } if block.is_a? Proc }.
|
21
|
+
map {|x| ind.nil? ? x : x[ind] }.
|
22
|
+
compact.
|
23
|
+
sort
|
24
|
+
unless dim.zero?
|
25
|
+
reductor = (base.size * dim).round
|
26
|
+
puts reductor
|
27
|
+
worker = worker[reductor..base.size - reductor]
|
28
|
+
puts worker.size
|
29
|
+
end
|
30
|
+
result = {}
|
31
|
+
|
32
|
+
result[:size] = worker.size
|
33
|
+
result[:min] = worker.first
|
34
|
+
result[:avg] = (worker.reduce(:+) / result[:size]).round(precision+1)
|
35
|
+
result[:lower] = worker[ (result[:size] * 1 / 4).round ]
|
36
|
+
result[:median] = worker[ (result[:size] * 2 / 4).round ]
|
37
|
+
result[:upper] = worker[ (result[:size] * 3 / 4).round ]
|
38
|
+
result[:max] = worker.last
|
39
|
+
|
40
|
+
result[:output] = result.
|
41
|
+
reject{|k,_| k == :size}.
|
42
|
+
map{|k,v| { type: k, value: v, output: "#{k}: #{format(format, v)}".colorize(k==:avg ? :light_yellow : :white) } }.
|
43
|
+
sort_by{|x| x[:value]}.
|
44
|
+
map{|x| x[:output]}
|
45
|
+
output = "[" +
|
46
|
+
" size: #{format '%6d', result[:size]} | ".light_white +
|
47
|
+
output.join(' | ') +
|
48
|
+
" ]"
|
49
|
+
|
50
|
+
puts result[:output] if print
|
51
|
+
result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cotcube-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin L. Tischendorf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- cotcube-helpers.gemspec
|
83
83
|
- lib/cotcube-helpers.rb
|
84
84
|
- lib/cotcube-helpers/array_ext.rb
|
85
|
+
- lib/cotcube-helpers/datetime_ext.rb
|
85
86
|
- lib/cotcube-helpers/enum_ext.rb
|
86
87
|
- lib/cotcube-helpers/hash_ext.rb
|
87
88
|
- lib/cotcube-helpers/input.rb
|
@@ -89,6 +90,7 @@ files:
|
|
89
90
|
- lib/cotcube-helpers/range_ext.rb
|
90
91
|
- lib/cotcube-helpers/reduce.rb
|
91
92
|
- lib/cotcube-helpers/simple_output.rb
|
93
|
+
- lib/cotcube-helpers/simple_series_stats.rb
|
92
94
|
- lib/cotcube-helpers/string_ext.rb
|
93
95
|
- lib/cotcube-helpers/subpattern.rb
|
94
96
|
- lib/cotcube-helpers/swig/date.rb
|