time_trap 0.0.3 → 0.0.5
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/.yardopts +1 -0
- data/README.md +6 -22
- data/lib/timetrap/deque.rb +11 -1
- data/lib/timetrap.rb +81 -5
- data/spec/{timetrap/timetrap_spec.rb → timetrap_spec.rb} +12 -0
- data/time_trap.gemspec +8 -8
- metadata +40 -27
- data/lib/timetrap/timetrap.rb +0 -56
- data/lib/timetrap/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d30223f65f22ddaf031ee3b26a82f4ae4dc575a4
|
4
|
+
data.tar.gz: 6211bb8bcceb931d380cdf3baf4421ed921bc4da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69686f11676f70fd77ab8ae7ec0fac6f4785f50b50773867d3ef2f2f0b4ce4015da44c7d42d87304eff0ed0e3f7a6499b29628ddaf259a2d885ad4a3b5d1e116
|
7
|
+
data.tar.gz: 832d5fb56b1685ed60b13ae06f92e22c654d51c65996f374ad9fbf1c28f0478feeb10eeedbfbd5aa07fd985957f9862d0297363d2ebd1ac466ebda54a706c169
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/README.md
CHANGED
@@ -1,33 +1,17 @@
|
|
1
|
-
#
|
1
|
+
# TimeTrap
|
2
2
|
|
3
|
-
|
3
|
+
TimeTrap impelents a moving window data structure for keeping track of top-k things
|
4
4
|
as they are created (eg. tweets, exceptions in a log file, or :Q
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
And then execute:
|
13
|
-
|
14
|
-
$ bundle
|
15
|
-
|
16
|
-
Or install it yourself as:
|
17
|
-
|
18
|
-
$ gem install time_trap
|
8
|
+
|||
|
9
|
+
|---|---|
|
10
|
+
|bundler|gem 'time_trap'|
|
11
|
+
|raw gem|gem install time_trap|
|
19
12
|
|
20
13
|
## Usage
|
21
14
|
|
22
15
|
tt = TimeTrap.new
|
23
16
|
tt.add("benedict")
|
24
17
|
tt.add("cumberbatch")
|
25
|
-
|
26
|
-
|
27
|
-
## Contributing
|
28
|
-
|
29
|
-
1. Fork it ( http://github.com/<my-github-username>/timetrap/fork )
|
30
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
31
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
32
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
33
|
-
5. Create new Pull Request
|
data/lib/timetrap/deque.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# Deque is an inplementation of a [double ended queue] (https://en.wikipedia.org/wiki/Double-ended_queue)
|
2
|
+
# currently implemented using an array
|
1
3
|
class Deque
|
2
4
|
attr_accessor :queue
|
3
5
|
|
@@ -5,27 +7,35 @@ class Deque
|
|
5
7
|
@queue = []
|
6
8
|
end
|
7
9
|
|
10
|
+
# @return [Object] return earliest object added
|
8
11
|
def first
|
9
12
|
return @queue.last
|
10
13
|
end
|
11
14
|
|
15
|
+
# @return [Object] return most recent object added
|
12
16
|
def last
|
13
17
|
return @queue.first
|
14
18
|
end
|
15
|
-
|
19
|
+
|
20
|
+
# @param [FixNum] time time value to pushed into queue
|
16
21
|
def push(time=Time.now.to_i)
|
17
22
|
@queue << time
|
18
23
|
return time
|
19
24
|
end
|
20
25
|
|
26
|
+
# @return [FixNum] return most recent time added
|
21
27
|
def pop
|
22
28
|
return @queue.shift
|
23
29
|
end
|
24
30
|
|
31
|
+
# @return [FixNum] return count of objects in queue
|
25
32
|
def count
|
26
33
|
return @queue.size
|
27
34
|
end
|
28
35
|
|
36
|
+
# @param [FixNum] start_time beginning of time range for window
|
37
|
+
# @param [FixNum] end_time end of time range for window
|
38
|
+
# @return [Array] returns array of time entries contained in window
|
29
39
|
def window(start_time, end_time)
|
30
40
|
ret = @queue.select {|data_time| data_time >= start_time && data_time <= end_time }
|
31
41
|
return ret
|
data/lib/timetrap.rb
CHANGED
@@ -1,8 +1,84 @@
|
|
1
|
-
require "timetrap/timetrap"
|
2
|
-
require "timetrap/version"
|
3
|
-
require "timetrap/deque"
|
4
1
|
|
2
|
+
# TimeTrap is a data structure that allows stores instances of keys added over time.
|
3
|
+
# At its core, TimeTrap is a hash where keys are data instances tracked and values are
|
4
|
+
# arrays of time(s) when teh data instance occurred.
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
class TimeTrap
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@tt = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Add an instance of value to timetrap. time defaults to seconds since
|
14
|
+
# epoch unless you provide a value.
|
15
|
+
def add(value, time=Time.now.to_i)
|
16
|
+
@tt[value] ||= Deque.new
|
17
|
+
return @tt[value].push(time)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [Object] value key to retrieve.
|
21
|
+
# @return [Array] array of time instances the value was added
|
22
|
+
def get(value)
|
23
|
+
ret = @tt[value].nil? ? nil : @tt[value].queue
|
24
|
+
return ret
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Array] array of values that have been added
|
28
|
+
def keys
|
29
|
+
return @tt.keys
|
30
|
+
end
|
31
|
+
|
32
|
+
# allows block code to be run on each entry in TimeTrap
|
33
|
+
def each(&block)
|
34
|
+
@tt.each(&block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# removes k/v from TimeTrap if block code evaluates to true
|
38
|
+
# @return [TimeTrap] TimeTrap instance with deleted entries removed
|
39
|
+
def delete_if(&block)
|
40
|
+
@tt.delete_if(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Array] of values sorted by argued block code
|
44
|
+
def sort_by(&block)
|
45
|
+
@tt.sort_by(&block)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @param [Fixnum] rank number of entries to return
|
49
|
+
# @return [Array] array of keys sorted by number of instances
|
50
|
+
def top(rank)
|
51
|
+
ret = @tt.sort_by {|k,v| -v.count}.map{|k,v| k}
|
52
|
+
return ret[0..rank - 1]
|
53
|
+
end
|
54
|
+
|
55
|
+
# @param [Fixnum] secs number of seconds before current time for window
|
56
|
+
# @return [Hash] returns hash of values in window key=added data, value = count
|
57
|
+
# of occurences in last argued secondswindow
|
58
|
+
def last(secs)
|
59
|
+
t = Time.now.to_i
|
60
|
+
return window(t - secs, t)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param [Object] key key to look up in TimeTrap
|
64
|
+
# @return [bool] obvious??
|
65
|
+
def has_key?(key)
|
66
|
+
return @tt.has_key?(key)
|
67
|
+
end
|
68
|
+
|
69
|
+
# @return count of distinct keys which have been added
|
70
|
+
def count
|
71
|
+
return @tt.count
|
72
|
+
end
|
73
|
+
|
74
|
+
# @param [FixNum] start_sec beginning on time frame
|
75
|
+
# @param [FixNum] end_sec end of time frame
|
76
|
+
# @return [Hash] key = value added to TimeTrap, value = count of instances in the window
|
77
|
+
def window(start_sec, end_sec)
|
78
|
+
ret = {}
|
79
|
+
@tt.each {|k,v| ret[k] = v.window(start_sec, end_sec).count if v.window(start_sec, end_sec).count > 0}
|
80
|
+
return ret
|
81
|
+
end
|
8
82
|
end
|
83
|
+
|
84
|
+
require 'timetrap/deque'
|
@@ -16,6 +16,18 @@ describe TimeTrap do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
context "#get" do
|
20
|
+
it "allows retrieval of values" do
|
21
|
+
t = Time.now.to_i
|
22
|
+
ttrap.add("test_1", t)
|
23
|
+
expect(ttrap.get("test_1")).to match_array([t])
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns nil for keys that haven't been added" do
|
27
|
+
expect(ttrap.get("test_1")).to be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
19
31
|
context "#count" do
|
20
32
|
it "keeps count of objects added" do
|
21
33
|
time = ttrap.add("test_1")
|
data/time_trap.gemspec
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'timetrap/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
6
|
spec.name = "time_trap"
|
8
|
-
spec.version =
|
7
|
+
spec.version = "0.0.5"
|
9
8
|
spec.authors = ["Pat Farrell"]
|
10
9
|
spec.email = ["mr.patfarrell@gmail.com"]
|
11
10
|
spec.summary = %q{"exposes a data structure suitable for capturing and inspecting moving windows of data"}
|
12
11
|
spec.description = %q{"timetrap is a work in progress to create a simple data strucutre that allows for windowed inspection of counts added to a hash"}
|
13
|
-
spec.homepage = "
|
12
|
+
spec.homepage = "https://rubygems.org/gems/time_trap"
|
14
13
|
spec.license = "MIT"
|
15
14
|
|
16
15
|
spec.files = `git ls-files -z`.split("\x0")
|
@@ -20,9 +19,10 @@ Gem::Specification.new do |spec|
|
|
20
19
|
|
21
20
|
|
22
21
|
spec.add_development_dependency "bundler", "~> 1.5"
|
23
|
-
spec.add_development_dependency "rake"
|
24
|
-
spec.add_development_dependency "rspec"
|
25
|
-
spec.add_development_dependency "simplecov"
|
26
|
-
spec.add_development_dependency "yard"
|
27
|
-
spec.add_development_dependency "byebug"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.1"
|
23
|
+
spec.add_development_dependency "rspec", "~> 2.14"
|
24
|
+
spec.add_development_dependency "simplecov", "~> 0.8"
|
25
|
+
spec.add_development_dependency "yard", "~> 0.8"
|
26
|
+
spec.add_development_dependency "byebug", "~> 2.7"
|
27
|
+
spec.add_development_dependency "markdown", "~> 1.1"
|
28
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: time_trap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Farrell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -28,72 +28,86 @@ dependencies:
|
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '10.1'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '10.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2.14'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '2.14'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: simplecov
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '0.8'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '0.8'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
75
|
+
version: '0.8'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
82
|
+
version: '0.8'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: byebug
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '2.7'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.7'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: markdown
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.1'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
110
|
+
version: '1.1'
|
97
111
|
description: "\"timetrap is a work in progress to create a simple data strucutre that
|
98
112
|
allows for windowed inspection of counts added to a hash\""
|
99
113
|
email:
|
@@ -104,19 +118,18 @@ extra_rdoc_files: []
|
|
104
118
|
files:
|
105
119
|
- ".gitignore"
|
106
120
|
- ".rspec"
|
121
|
+
- ".yardopts"
|
107
122
|
- Gemfile
|
108
123
|
- LICENSE.txt
|
109
124
|
- README.md
|
110
125
|
- Rakefile
|
111
126
|
- lib/timetrap.rb
|
112
127
|
- lib/timetrap/deque.rb
|
113
|
-
- lib/timetrap/timetrap.rb
|
114
|
-
- lib/timetrap/version.rb
|
115
128
|
- spec/spec_helper.rb
|
116
129
|
- spec/timetrap/deque_spec.rb
|
117
|
-
- spec/
|
130
|
+
- spec/timetrap_spec.rb
|
118
131
|
- time_trap.gemspec
|
119
|
-
homepage:
|
132
|
+
homepage: https://rubygems.org/gems/time_trap
|
120
133
|
licenses:
|
121
134
|
- MIT
|
122
135
|
metadata: {}
|
@@ -144,5 +157,5 @@ summary: "\"exposes a data structure suitable for capturing and inspecting movin
|
|
144
157
|
test_files:
|
145
158
|
- spec/spec_helper.rb
|
146
159
|
- spec/timetrap/deque_spec.rb
|
147
|
-
- spec/
|
160
|
+
- spec/timetrap_spec.rb
|
148
161
|
has_rdoc:
|
data/lib/timetrap/timetrap.rb
DELETED
@@ -1,56 +0,0 @@
|
|
1
|
-
class TimeTrap
|
2
|
-
include Enumerable
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
@tt = {}
|
6
|
-
end
|
7
|
-
|
8
|
-
def add(value, time=Time.now.to_i)
|
9
|
-
@tt[value] ||= Deque.new
|
10
|
-
return @tt[value].push(time)
|
11
|
-
end
|
12
|
-
|
13
|
-
def get(value)
|
14
|
-
return @tt[value].queue
|
15
|
-
end
|
16
|
-
|
17
|
-
def keys
|
18
|
-
return @tt.keys
|
19
|
-
end
|
20
|
-
|
21
|
-
def each(&block)
|
22
|
-
@tt.each(&block)
|
23
|
-
end
|
24
|
-
|
25
|
-
def delete_if(&block)
|
26
|
-
@tt.delete_if(&block)
|
27
|
-
end
|
28
|
-
|
29
|
-
def sort_by(&block)
|
30
|
-
@tt.sort_by(&block)
|
31
|
-
end
|
32
|
-
|
33
|
-
def top(rank)
|
34
|
-
ret = @tt.sort_by {|k,v| -v.count}.map{|k,v| k}
|
35
|
-
return ret[0..rank - 1]
|
36
|
-
end
|
37
|
-
|
38
|
-
def last(secs)
|
39
|
-
t = Time.now.to_i
|
40
|
-
return window(t - secs, t)
|
41
|
-
end
|
42
|
-
|
43
|
-
def has_key?(key)
|
44
|
-
return @tt.has_key?(key)
|
45
|
-
end
|
46
|
-
|
47
|
-
def count
|
48
|
-
return @tt.count
|
49
|
-
end
|
50
|
-
|
51
|
-
def window(start_sec, end_sec)
|
52
|
-
ret = {}
|
53
|
-
@tt.each {|k,v| ret[k] = v.window(start_sec, end_sec).count if v.window(start_sec, end_sec).count > 0}
|
54
|
-
return ret
|
55
|
-
end
|
56
|
-
end
|
data/lib/timetrap/version.rb
DELETED