Class: Tilia::VObject::FreeBusyData

Inherits:
Object
  • Object
show all
Defined in:
lib/tilia/v_object/free_busy_data.rb

Overview

FreeBusyData is a helper class that manages freebusy information.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start, ending) ⇒ array

A list of free-busy times.

RUBY: attr_accessor :data



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/tilia/v_object/free_busy_data.rb', line 20

def initialize(start, ending)
  @start = start
  @end = ending
  @data = []

  @data << {
    'start' => @start,
    'end'   => @end,
    'type'  => 'FREE'
  }
end

Instance Attribute Details

#dataObject (readonly)

Returns the value of attribute data.



146
147
148
# File 'lib/tilia/v_object/free_busy_data.rb', line 146

def data
  @data
end

Instance Method Details

#add(start, ending, type) ⇒ void

This method returns an undefined value.

Adds free or busytime to the data.

Parameters:

  • start (Fixnum)
  • end (Fixnum)
  • type (String)

    FREE, BUSY, BUSY-UNAVAILABLE or BUSY-TENTATIVE



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/tilia/v_object/free_busy_data.rb', line 38

def add(start, ending, type)
  if start > @end || ending < @start
    # This new data is outside our timerange.
    return nil
  end

  if start < @start
    # The item starts before our requested time range
    start = @start
  end
  if ending > @end
    # The item ends after our requested time range
    ending = @end
  end

  # Finding out where we need to insert the new item.
  current_index = 0
  current_index += 1 while start > @data[current_index]['end']

  # The standard insertion point will be one _after_ the first
  # overlapping item.
  insert_start_index = current_index + 1

  new_item = {
    'start' => start,
    'end'   => ending,
    'type'  => type
  }

  preceeding_item = @data[insert_start_index - 1]
  if @data[insert_start_index - 1]['start'] == start
    # The old item starts at the exact same point as the new item.
    insert_start_index -= 1
  end

  # Now we know where to insert the item, we need to know where it
  # starts overlapping with items on the tail end. We need to start
  # looking one item before the insertStartIndex, because it's possible
  # that the new item 'sits inside' the previous old item.
  if insert_start_index > 0
    current_index = insert_start_index - 1
  else
    current_index = 0
  end

  current_index += 1 while ending > @data[current_index]['end']

  # What we are about to insert into the array
  new_items = [new_item]

  # This is the amount of items that are completely overwritten by the
  # new item.
  items_to_delete = current_index - insert_start_index
  items_to_delete += 1 if @data[current_index]['end'] <= ending

  # If itemsToDelete was -1, it means that the newly inserted item is
  # actually sitting inside an existing one. This means we need to split
  # the item at the current position in two and insert the new item in
  # between.
  if items_to_delete == -1
    items_to_delete = 0
    if new_item['end'] < preceeding_item['end']
      new_items << {
        'start' => new_item['end'] + 1,
        'end'   => preceeding_item['end'],
        'type'  => preceeding_item['type']
      }
    end
  end

  @data[insert_start_index, items_to_delete] = new_items

  do_merge = false
  merge_offset = insert_start_index
  merge_item = new_item
  merge_delete = 1

  # Ruby knows negative indices as well!
  if insert_start_index > 0 && @data.size > insert_start_index - 1
    # Updating the start time of the previous item.
    @data[insert_start_index - 1]['end'] = start

    # If the previous and the current are of the same type, we can
    # merge them into one item.
    if @data[insert_start_index - 1]['type'] == @data[insert_start_index]['type']
      do_merge = true
      merge_offset -= 1
      merge_delete += 1
      merge_item['start'] = @data[insert_start_index - 1]['start']
    end
  end

  if @data.size > insert_start_index + 1
    # Updating the start time of the next item.
    @data[insert_start_index + 1]['start'] = ending

    # If the next and the current are of the same type, we can
    # merge them into one item.
    if @data[insert_start_index + 1]['type'] == @data[insert_start_index]['type']
      do_merge = true
      merge_delete += 1
      merge_item['end'] = @data[insert_start_index + 1]['end']
    end
  end

  @data[merge_offset, merge_delete] = merge_item if do_merge
end