cross_time_calculation 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ *.swp
2
+ .DS_Store
3
+ *.gem
@@ -0,0 +1,26 @@
1
+ Cross Time calculation
2
+ ==================================================
3
+ If you want to compute the same user's online time from server log, who comes from multiple clients, so you need to remove duplicate parts.
4
+
5
+ Installation
6
+ --------------------------------------------------
7
+ ```zsh
8
+ gem install cross_time_calculation
9
+ ```
10
+
11
+ Usage
12
+ --------------------------------------------------
13
+
14
+ ```ruby
15
+ require 'time'
16
+ require 'cross_time_calculation'
17
+
18
+ @t1 = DateTime.parse("20130512").to_time
19
+ @t2 = @t1 + 33
20
+ @ctc = CrossTimeCalculation.new
21
+ @ctc.add @t1, @t2
22
+
23
+ @ctc.total_seconds # => 33
24
+ ```
25
+
26
+ See more complicated example in unit test
@@ -0,0 +1,10 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'cross_time_calculation'
5
+ s.version = File.read("VERSION").strip
6
+ s.date = '2013-06-09'
7
+ s.summary = "Cross Time calculation"
8
+ s.description = File.read("README.markdown").split("\n\n")[0].split(/====+/)[1].strip
9
+ s.authors = ["David Chen"]
10
+ s.email = 'mvjome@gmail.com'
11
+ s.homepage = 'http://github.com/mvj3/cross_time_calculation'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = Dir.glob("test/**/*.rb")
15
+ s.require_paths = ["lib"]
16
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: UTF-8
2
+
3
+ class CrossTimeCalculation
4
+ TimePoint = Struct.new(:t, :status) if not defined? TimePoint
5
+ attr_accessor :time_points
6
+
7
+ def initialize
8
+ self.time_points = Array.new
9
+ end
10
+
11
+ def add *time_begin_and_end
12
+ # init TimePoint pair
13
+ tb = TimePoint.new(time_begin_and_end[0], :started_at)
14
+ te = TimePoint.new(time_begin_and_end[1], :finished_at)
15
+
16
+ # validate data
17
+ raise "At least the begin time should exist" if not tb.t
18
+ raise "The begin time should not larger than the end time" if te.t && (tb.t > te.t)
19
+
20
+ # insert it and sort
21
+ self.time_points << tb
22
+ self.time_points << te if te.t
23
+ self.time_points = self.time_points.uniq {|i| "#{i.t}#{i.status}" }.sort {|a, b| a.t.to_i <=> b.t.to_i }
24
+
25
+ # TODO optimize search with idx
26
+ loop do
27
+ to_removes = []
28
+ self.time_points.each_with_index do |tp, idx|
29
+ post_tp = self.time_points[idx+1]
30
+ next if post_tp.nil?
31
+ # delete the first one if they are all finished_at
32
+ to_removes << tp if (tp.status == :finished_at) && (post_tp.status == :finished_at)
33
+ # delete the later one if they are all started_at
34
+ to_removes << post_tp if (tp.status == :started_at) && (post_tp.status == :started_at)
35
+ end
36
+ self.time_points -= to_removes
37
+
38
+ break if data_valid?
39
+ end
40
+
41
+ return self
42
+ end
43
+
44
+ def total_seconds
45
+ result = 0
46
+ self.time_points.each_slice(2) do |a|
47
+ end_time = a[1] ? a[1].t : Time.now
48
+ if a[0] && a[0].t
49
+ t = (end_time - a[0].t)
50
+ result += t
51
+ end
52
+ end
53
+ result
54
+ end
55
+
56
+ # start time and end time interval is supposed to exist
57
+ def data_valid?
58
+ valids = []
59
+ self.time_points.each_slice(2) do |tp_start, tp_finish|
60
+ next if tp_finish.nil?
61
+ valids << (tp_start.status != tp_finish.status)
62
+ end
63
+ valids.count(false).zero?
64
+ end
65
+
66
+ end
@@ -0,0 +1,77 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test/unit'
4
+ require 'time'
5
+ require 'cross_time_calculation'
6
+
7
+ class TestCrossTimeCalculation < Test::Unit::TestCase
8
+ def setup
9
+ # the first pair
10
+ @t1 = DateTime.parse("20130512").to_time
11
+ @t2 = @t1 + 33
12
+
13
+ @ctc = CrossTimeCalculation.new
14
+ @ctc.add @t1, @t2
15
+
16
+ # the second pair
17
+ @t3 = DateTime.parse("20130512 10:51:03").to_time
18
+ @t4 = DateTime.parse("20130512 14:21:24").to_time
19
+
20
+ # the third pair
21
+ @t5 = DateTime.parse("20130512 18:32:28").to_time
22
+ @t6 = DateTime.parse("20130512 23:19:31").to_time
23
+
24
+ # the forth pair crossed with the third pair
25
+ @t7 = DateTime.parse("20130512 20").to_time
26
+ @t8 = DateTime.parse("20130513 13").to_time
27
+ end
28
+
29
+ def test_empty
30
+ assert_equal CrossTimeCalculation.new.total_seconds, 0
31
+ end
32
+
33
+ def test_no_time_end
34
+ assert_nothing_raised do
35
+ @ctc.add Time.now
36
+ end
37
+ end
38
+
39
+ def test_one_time_point
40
+ assert_equal @ctc.total_seconds, 33
41
+ end
42
+
43
+ def test_more_time_points
44
+ @ctc.add @t3, @t4
45
+ @ctc.add @t5, @t6
46
+ compute = (@t2 - @t1) + (@t4 - @t3) + (@t6 - @t5)
47
+ compare = (@ctc.total_seconds - compute).abs < 1
48
+ assert_equal compare, true
49
+ end
50
+
51
+ def test_more_time_points_with_cross
52
+ assert_equal load_more_time_points, true
53
+ end
54
+
55
+ def test_dup_time_points_with_cross
56
+ assert_equal load_more_time_points(true), true
57
+ end
58
+
59
+ private
60
+ def load_more_time_points dup = false
61
+ @ctc.add @t3, @t4
62
+ @ctc.add @t5, @t6
63
+ @ctc.add @t7, @t8
64
+ @ctc.add @t7, @t8 if dup
65
+
66
+ # user array to count appeared second
67
+ @seconds = []
68
+ [[@t1, @t2], [@t3, @t4], [@t5, @t6], [@t7, @t8], (dup ? [@t7, @t8] : nil)].compact.each do |tb, te|
69
+ next if tb.nil?
70
+ new_idx = tb - @t1
71
+ (te-tb).to_i.times {|idx| @seconds[new_idx+idx] = 1 }
72
+ end
73
+
74
+ (@seconds.count(1) - @ctc.total_seconds).abs < 3
75
+ end
76
+
77
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cross_time_calculation
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Chen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-09 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: If you want to compute the same user's online time from server log, who
15
+ comes from multiple clients, so you need to remove duplicate parts.
16
+ email: mvjome@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - README.markdown
23
+ - Rakefile
24
+ - VERSION
25
+ - cross_time_calculation.gemspec
26
+ - lib/cross_time_calculation.rb
27
+ - test/test_cross_time_calculation.rb
28
+ homepage: http://github.com/mvj3/cross_time_calculation
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.25
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Cross Time calculation
52
+ test_files:
53
+ - test/test_cross_time_calculation.rb