Module: Work

Defined in:
lib/work.rb

Overview

A module to (roughly) estimate productivity. Uses the ‘updated_at’ timestamp as a proxy.

Constant Summary collapse

BATCH_COUNT_CUTOFF =
500.0
BATCH_EFFICIENCY_CUTOFF =
20.0

Class Method Summary collapse

Class Method Details

.average_minutes_per_record(sessions, include_batch = false) ⇒ Object



130
131
132
# File 'lib/work.rb', line 130

def self.average_minutes_per_record(sessions, include_batch = false)
  (1.00 / average_records_per_minute(sessions, include_batch)).round(3)
end

.average_records_per_minute(sessions, include_batch = false) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
# File 'lib/work.rb', line 118

def self.average_records_per_minute(sessions, include_batch = false)
  return 0 if sessions.nil?
  i = 0
  t = 0
  sessions.each do |s|
    next if !include_batch && s[:batch]
    i += s[:count]
    t += s[:end] - s[:start]
  end
  ( i.to_f / (t / 60)).round(3)
end

.new_session(current_time) ⇒ Hash

Returns:

  • (Hash)


63
64
65
66
67
68
69
70
# File 'lib/work.rb', line 63

def self.new_session(current_time)
  return {
    start: current_time, # Time of session start
    end: nil,            # Time of session end
    count: 1,            # Number of records updated
    efficiency: 0      # Records updated per minute (at least 5 min per record, if only a single record was created)
  }
end

.sessions(records) ⇒ Array

Parameters:

  • records (An ActiveRecord scope)

    A session is a contiguous period of time in which the gap between updated records is no longer than 60 minutes

Returns:

  • (Array)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/work.rb', line 11

def self.sessions(records)
  return [] if records.none?

  r = records.to_a

  a = r.shift
  last_time = a.updated_at

  sessions = [ ]
  current_session = new_session(last_time)

  while r.count != 0
    a = r.shift

    current_time = a.updated_at

    # more than one hour between subsequent specimens
    # sessions ends
    if current_time - last_time > 3600.0

      current_session[:end] = last_time
      current_session[:end] = last_time + 5.minutes if current_session[:start] == current_session[:end] # at least 5 min per record, if only one record was created

#        if current_session[:count] == 1
#          current_session[:efficiency] = (1/5).round(3)
#        else
        current_session[:efficiency] = (current_session[:count].to_f / ((current_session[:end] - current_session[:start]) / 60.0)).round(3)
#        end

      # TODO: add efficiency comparison here
      current_session[:batch] = true if (current_session[:count] > BATCH_COUNT_CUTOFF) &&  (current_session[:efficiency] > BATCH_EFFICIENCY_CUTOFF )

      sessions.push current_session
      current_session = new_session(current_time)

      # session continues
    else
      current_session[:count] += 1
    end
    last_time = current_time
  end

  current_session[:end] = last_time
  current_session[:end] = last_time + 5.minutes if current_session[:start] == current_session[:end]
  current_session[:efficiency] = (current_session[:count].to_f / ((current_session[:end] - current_session[:start]) / 60.0)).round(3)
  current_session[:batch] = true if (current_session[:count] > BATCH_COUNT_CUTOFF) &&  (current_session[:efficiency] > BATCH_EFFICIENCY_CUTOFF )
  sessions.push current_session

  sessions
end

.sum_count(sessions, include_batch = false) ⇒ Object



108
109
110
111
112
113
114
115
116
# File 'lib/work.rb', line 108

def self.sum_count(sessions, include_batch = false)
  return 0 if sessions.nil?
  i = 0
  sessions.each do |s|
    next if !include_batch && s[:batch]
    i += s[:count]
  end
  i
end

.sum_count_without_batch_sessions(sessions) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/work.rb', line 98

def self.sum_count_without_batch_sessions(sessions)
  return 0 if sessions.nil?
  i = 0
  sessions.each do |s|
    next if s[:batch]
    i += s[:count]
  end
  i
end

.total_batch_sessions(sessions) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/work.rb', line 88

def self.total_batch_sessions(sessions)
  return 0 if sessions.nil?
  i = 0
  sessions.each do |s|
    next if !s[:batch]
    i += 1 if s[:count]
  end
  i
end

.total_time(sessions, include_batch = false) ⇒ Integer?

Returns in seconds.

Returns:

  • (Integer, nil)

    in seconds



74
75
76
77
78
79
80
81
82
# File 'lib/work.rb', line 74

def self.total_time(sessions, include_batch = false)
  return 0 if sessions.nil?
  t = 0
  sessions.each do |s|
    next if !include_batch && s[:batch]
    t += s[:end] - s[:start]
  end
  t
end

.total_time_in_hours(sessions, include_batch = false) ⇒ Object



84
85
86
# File 'lib/work.rb', line 84

def self.total_time_in_hours(sessions, include_batch = false)
  ( total_time(sessions, include_batch) / 3600.0).round(2)
end