Class: PatronusFati::Presence
- Inherits:
-
Object
- Object
- PatronusFati::Presence
- Defined in:
- lib/patronus_fati/presence.rb
Overview
This class holds two hours worth of presence data at minutely resolution. Tests can be done to see whether or not whatever this is tracking was present at a specific time or during a specific time interval.
Instance Attribute Summary collapse
-
#current_presence ⇒ void
Returns the value of attribute current_presence.
-
#first_seen ⇒ void
Returns the value of attribute first_seen.
-
#last_presence ⇒ void
Returns the value of attribute last_presence.
-
#window_start ⇒ void
Returns the value of attribute window_start.
Instance Method Summary collapse
-
#bit_for_time(reference_window, timestamp) ⇒ void
Translate a timestamp relative to the provided reference window into an appropriate bit within our bit field.
-
#current_bit_offset ⇒ void
Get the bit representing our current interval within the window.
-
#current_window_start ⇒ void
Returns the unix timestamp of the beginning of the current window.
-
#dead? ⇒ Boolean
Returns true if we have no data points indicating we’ve seen the presence of this instance in the entirety of our time window.
-
#initialize ⇒ Presence
constructor
A new instance of Presence.
-
#last_visible ⇒ void
Provides the beginning of the last interval when the tracked object was seen.
- #last_window_start ⇒ void
-
#mark_visible ⇒ void
Mark the current interval as having been seen in the presence field.
-
#rotate_presence ⇒ void
Should be called before reading or writing from/to the current_presence to ensure it is pointing at the appropriate bitfield.
-
#set_first_seen ⇒ void
Set the time we first saw whatever we’re tracking to be the beginning of the current interval.
-
#time_for_bit(reference_window, bit) ⇒ void
Translate a bit into an absolute unix time relative to the reference window.
-
#visible_since?(unix_time) ⇒ Boolean
Checks to see if the presence of the tracked object has been visible at all since the provided time.
-
#visible_time ⇒ void
Returns the duration in seconds of how long the specific object was absolutely seen.
Constructor Details
#initialize ⇒ Presence
Returns a new instance of Presence.
34 35 36 37 38 |
# File 'lib/patronus_fati/presence.rb', line 34 def initialize self.current_presence = BitField.new(WINDOW_INTERVALS) self.last_presence = BitField.new(WINDOW_INTERVALS) self.window_start = current_window_start end |
Instance Attribute Details
#current_presence ⇒ void
Returns the value of attribute current_presence.
6 7 8 |
# File 'lib/patronus_fati/presence.rb', line 6 def current_presence @current_presence end |
#first_seen ⇒ void
Returns the value of attribute first_seen.
6 7 8 |
# File 'lib/patronus_fati/presence.rb', line 6 def first_seen @first_seen end |
#last_presence ⇒ void
Returns the value of attribute last_presence.
6 7 8 |
# File 'lib/patronus_fati/presence.rb', line 6 def last_presence @last_presence end |
#window_start ⇒ void
Returns the value of attribute window_start.
6 7 8 |
# File 'lib/patronus_fati/presence.rb', line 6 def window_start @window_start end |
Instance Method Details
#bit_for_time(reference_window, timestamp) ⇒ void
Translate a timestamp relative to the provided reference window into an appropriate bit within our bit field.
10 11 12 13 14 |
# File 'lib/patronus_fati/presence.rb', line 10 def bit_for_time(reference_window, ) offset = - reference_window raise ArgumentError if offset < 0 || offset >= WINDOW_LENGTH (offset / INTERVAL_DURATION) + 1 end |
#current_bit_offset ⇒ void
Get the bit representing our current interval within the window
17 18 19 |
# File 'lib/patronus_fati/presence.rb', line 17 def current_bit_offset bit_for_time(window_start, Time.now.to_i) end |
#current_window_start ⇒ void
Returns the unix timestamp of the beginning of the current window.
22 23 24 25 |
# File 'lib/patronus_fati/presence.rb', line 22 def current_window_start ts = Time.now.to_i ts - (ts % WINDOW_LENGTH) end |
#dead? ⇒ Boolean
Returns true if we have no data points indicating we’ve seen the presence of this instance in the entirety of our time window.
29 30 31 32 |
# File 'lib/patronus_fati/presence.rb', line 29 def dead? rotate_presence current_presence.bits == 0 && last_presence.bits == 0 end |
#last_visible ⇒ void
Provides the beginning of the last interval when the tracked object was seen. This could probably be optimized with a B tree search or the like but this is more than enough for now.
47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/patronus_fati/presence.rb', line 47 def last_visible rotate_presence return nil if dead? if (bit = current_presence.highest_bit_set) time_for_bit(window_start, bit) else time_for_bit(last_window_start, last_presence.highest_bit_set) end end |
#last_window_start ⇒ void
40 41 42 |
# File 'lib/patronus_fati/presence.rb', line 40 def last_window_start window_start - WINDOW_LENGTH end |
#mark_visible ⇒ void
Mark the current interval as having been seen in the presence field. Will handle rotation if the window has slipped.
61 62 63 64 65 66 |
# File 'lib/patronus_fati/presence.rb', line 61 def mark_visible rotate_presence set_first_seen unless first_seen self.current_presence.set_bit(current_bit_offset) end |
#rotate_presence ⇒ void
Should be called before reading or writing from/to the current_presence to ensure it is pointing at the appropriate bitfield. When we shift into a new bit window, this method will move the current window into the old one, and reset the current bit field.
72 73 74 75 76 77 78 79 |
# File 'lib/patronus_fati/presence.rb', line 72 def rotate_presence cws = current_window_start return if window_start == cws self.last_presence = current_presence self.window_start = cws self.current_presence = BitField.new(WINDOW_INTERVALS) end |
#set_first_seen ⇒ void
Set the time we first saw whatever we’re tracking to be the beginning of the current interval. This prevents negative durations in the event we only see it once.
84 85 86 87 |
# File 'lib/patronus_fati/presence.rb', line 84 def set_first_seen cur_time = Time.now.to_i self.first_seen = cur_time - (cur_time % INTERVAL_DURATION) end |
#time_for_bit(reference_window, bit) ⇒ void
Translate a bit into an absolute unix time relative to the reference window
91 92 93 94 |
# File 'lib/patronus_fati/presence.rb', line 91 def time_for_bit(reference_window, bit) raise ArgumentError if bit <= 0 || bit > WINDOW_INTERVALS reference_window + (INTERVAL_DURATION * (bit - 1)) end |
#visible_since?(unix_time) ⇒ Boolean
Checks to see if the presence of the tracked object has been visible at all since the provided time. Currently this is dependent on visible_at? and can perform at most WINDOW_INTERVALS - 1 calls.
This could be significantly sped up by a direct bit field check against both the presence fields.
102 103 104 105 106 107 |
# File 'lib/patronus_fati/presence.rb', line 102 def visible_since?(unix_time) rotate_presence return false unless (lv = last_visible) unix_time <= lv end |
#visible_time ⇒ void
Returns the duration in seconds of how long the specific object was absolutely seen. One additional interval duration is added to this length as we consider to have seen the tracked object for the entire duration of the interval not the length from the start of one interval to the start of the last interval, which makes logical sense (1 bit set is 1 interval duration, not zero seconds).
115 116 117 |
# File 'lib/patronus_fati/presence.rb', line 115 def visible_time (last_visible + INTERVAL_DURATION) - first_seen if first_seen && last_visible end |