class Symian::SupportGroup

Constants

ATTRIBUTES

setup readable/accessible attributes

TRACED_ATTRIBUTES

Public Class Methods

new(support_group_id, simulation, work_time_characterization, operator_characterizations) click to toggle source
# File lib/symian/support_group.rb, line 26
def initialize(support_group_id, simulation, work_time_characterization, operator_characterizations)
  @sgid = support_group_id
  @simulation = simulation

  # initialize needed_work_time_rng
  @needed_work_time_rv = ERV::RandomVariable.new(work_time_characterization)

  # create operators
  @operators = []

  if operator_characterizations.kind_of?(Hash)
    operator_characterizations = [ operator_characterizations ]
  end

  next_op_id = 1
  operator_characterizations.each do |x|
    x[:number].times do |y|
      op = Operator.new("OP#{next_op_id}_#{@sgid}", @sgid, x.reject { |k, v| k == :number })
      @operators << op
      next_op_id = next_op_id + 1
    end
  end

  # initialize incident queue and related tracking information
  @incident_queue = []
  @incident_queue_info = []
end

Public Instance Methods

initialize_at(time) click to toggle source
# File lib/symian/support_group.rb, line 55
def initialize_at(time)
  # find out which operators are off duty and schedule their comeback
  @operators_off_work = @operators.select do |x|
    !x.workshift.active_at?(time)
  end
  @operators_off_work.each do |op|
    t = op.workshift.secs_to_begin_of_shift(time)
    @simulation.new_event(Event::ET_OPERATOR_RETURNING, op.oid,
                          time + t, @sgid)
  end

  # find out which operators are on duty and schedule their leaving
  @available_operators = @operators - @operators_off_work
  @available_operators.each do |op|
    t = op.workshift.secs_to_end_of_shift(time)
    @simulation.new_event(Event::ET_OPERATOR_LEAVING, op.oid,
                          time + t, @sgid) unless t == WorkShift::Infinity
  end
end
new_incident(incident, time) click to toggle source
# File lib/symian/support_group.rb, line 76
def new_incident(incident, time)
  # increase number of visited SGs
  incident.visited_support_groups += 1

  incident_info = {
    # set up incident needed work time
    :needed_work_time => @needed_work_time_rv.next,
    # # reset queue_time_at_last_sg attribute
    # :queue_time => 0
  }

  # put incident at the end of the queue
  @incident_queue << [ incident, incident_info, time ]

  # update queue size tracking information
  @incident_queue_info << { :size => @incident_queue.size, :time => time }
  @simulation.new_event(Event::ET_SUPPORT_GROUP_QUEUE_SIZE_CHANGE, @incident_queue.size,
                        time, @sgid)

  # try to allocate operator
  try_to_allocate_operator(time)
end
operator_arrived_at_work(operator_id, time) click to toggle source
# File lib/symian/support_group.rb, line 117
def operator_arrived_at_work(operator_id, time)
  op = @operators.find{|x| x.oid == operator_id }
  @operators_off_work.delete(op)
  @available_operators << op
  try_to_allocate_operator(time)
  @simulation.new_event(Event::ET_OPERATOR_LEAVING, op.oid,
                        time + op.workshift.duration, @sgid)
end
operator_finished_working(operator_id, time) click to toggle source
# File lib/symian/support_group.rb, line 127
def operator_finished_working(operator_id, time)
  op = @operators.find{|x| x.oid == operator_id }
  if op.workshift.secs_to_end_of_shift(time) > 0
    @available_operators << op
  end
  try_to_allocate_operator(time)
end
operator_going_home(operator_id, time) click to toggle source
# File lib/symian/support_group.rb, line 108
def operator_going_home(operator_id, time)
  op = @operators.find{|x| x.oid == operator_id }
  @available_operators.delete_if{|x| x.oid == operator_id }
  @operators_off_work << op
  @simulation.new_event(Event::ET_OPERATOR_RETURNING, op.oid,
                        time + 86400 - op.workshift.duration, @sgid)
end
schedule_incident_for_reassignment(incident, incident_info, time) click to toggle source
# File lib/symian/support_group.rb, line 100
def schedule_incident_for_reassignment(incident, incident_info, time)
  @incident_queue.unshift [ incident, incident_info, time ]
  # update queue size tracking information
  @incident_queue_info << { :size => @incident_queue.size, :time => time }
  try_to_allocate_operator(time)
end

Private Instance Methods

try_to_allocate_operator(time) click to toggle source
# File lib/symian/support_group.rb, line 138
def try_to_allocate_operator(time)
  if !@available_operators.empty? and !@incident_queue.empty?
    op = @available_operators.shift
    i, inc_info, t = @incident_queue.shift

    # update incident tracking information
    queue_time = time.to_i - t.to_i
    i.add_tracking_information(:type => :queue,
                               :at => t,
                               :duration => queue_time,
                               :sg => @support_group_id)


    @simulation.new_event(Event::ET_SUPPORT_GROUP_QUEUE_SIZE_CHANGE,
                          @incident_queue.size, time, @sgid)
    @simulation.new_event(Event::ET_INCIDENT_ASSIGNMENT,
                          [ i.iid, op.oid ], time, @sgid)
    @simulation.new_event(Event::ET_OPERATOR_ACTIVITY_STARTS,
                          [ op.oid, i.iid ], time, @sgid)

    # assign updates inc_info
    report = op.assign(i, inc_info, time)
    finish_time = report[1]

    puts "finish_time: #{finish_time}, time: #{time}" if time > finish_time
    @simulation.new_event(Event::ET_OPERATOR_ACTIVITY_FINISHES,
                          [ op.oid, i.iid ], finish_time, @sgid)

    case report[0]
      when :incident_escalation
        @simulation.new_event(Event::ET_INCIDENT_ESCALATION,
                              i, finish_time, @sgid)
      when :operator_off_duty
        # TODO: implement configurable rescheduling policy
        @incident_queue << [ i, inc_info, finish_time ]
        @simulation.new_event(Event::ET_INCIDENT_RESCHEDULING,
                              [ i, inc_info, op.oid ], finish_time, @sgid)
    end
  end
end